c++oding="utf-8" ?>
工厂方法模式的核心是让子类决定实例化哪个类,通过抽象基类声明纯虚createproduct(),由派生类重写并返回std::unique_ptr,产品基类须有virtual析构函数。

工厂方法模式的核心是让子类决定实例化哪个类
它不是直接 new 一个具体类型,而是把“创建对象”这件事推迟到子类去实现。C++ 里最自然的做法是定义一个基类的纯虚函数 createProduct(),由派生类重写——这样调用方只依赖抽象接口,不耦合具体类型。
常见错误是把工厂逻辑写在构造函数里,或者在基类中直接 new 具体类,这会破坏开闭原则,也失去多态创建的意义。
- 基类工厂必须声明为抽象类(含纯虚
createProduct()) - 每个具体工厂继承它,并在重写的
createProduct()中返回对应的具体产品指针(通常用std::unique_ptr管理) - 产品本身也应是抽象基类,避免暴露具体类型的内存布局细节
用 std::unique_ptr 而不是 raw pointer 返回产品对象
裸指针(Product*)会让调用方承担释放责任,容易导致内存泄漏或重复 delete;而 std::unique_ptr<product></product> 明确表达了所有权转移,且能自动析构。
注意:如果产品类没有虚析构函数,std::unique_ptr<product></product> 在销毁时不会调用派生类析构函数——这是典型崩溃点。
- 务必在产品基类中声明
virtual ~Product() = default; - 工厂方法返回类型统一用
std::unique_ptr<product></product>,不要混用std::shared_ptr(除非真需要共享所有权) - 派生工厂中 new 出的对象,必须能被基类指针安全接管,即满足 Liskov 替换原则
避免在工厂内部做运行时类型判断(比如 if-else 判断字符串)
那种靠传入字符串决定创建哪种产品的写法,本质是简单工厂(Simple Factory),不属于 GoF 定义的工厂方法模式。工厂方法强调的是“多态创建”,靠类继承和重写实现,不是靠条件分支。
如果你发现代码里出现了类似 if (type == "A") return std::make_unique<producta>();</producta>,说明你正在退化成配置驱动的简单工厂——它灵活但失去了模式的意图和可扩展性。
- 真正的工厂方法模式,每个具体工厂类只负责一种产品,职责单一
- 新增产品时,只需添加新的产品类 + 新的具体工厂类,无需修改已有工厂逻辑
- 运行时选择哪个工厂,应由上层策略(如配置、用户输入、上下文)决定,而不是在单个工厂内做 switch
示例:一个可编译的最小可行片段
class Product {
public:
virtual ~Product() = default;
virtual void operation() = 0;
};
<p>class ConcreteProductA : public Product {
public:
void operation() override { /<em> ... </em>/ }
};</p><p>class Creator {
public:
virtual std::unique_ptr<product> createProduct() = 0;
};</product></p><p>class ConcreteCreatorA : public Creator {
public:
std::unique_ptr<product> createProduct() override {
return std::make_unique<concreteproducta>();
}
};</concreteproducta></product></p>
上面这段代码去掉注释就能通过 g++ -std=c++17 编译。关键点不在语法炫技,而在于:Creator 不知道 ConcreteProductA 的存在,ConcreteCreatorA 不依赖其他具体产品,调用方只跟 Creator 和 Product 打交道——这才是工厂方法在 C++ 里真正起作用的地方。
最容易被忽略的是虚析构和智能指针配合使用的必要性,漏掉任意一个,程序可能当场崩溃或静默泄露。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











