简单工厂不是GoF 23种设计模式之一,而是封装对象创建逻辑的编程习惯;其C++实现核心是用static函数+智能指针(如std::unique_ptr)根据参数返回子类对象,避免裸指针、硬编码类型和手动内存管理,并须声明虚析构函数确保安全销毁。
严格来说,简单工厂 并不在 GoF 23 种设计模式之列,它只是一个“编程习惯”或“封装创建逻辑的技巧”。但它常被当作学习 工厂方法 和 抽象工厂 的跳板。C++ 中实现它的核心是:用一个独立函数或静态方法,根据参数返回不同子类对象的指针(通常是 std::unique_ptr 或 std::shared_ptr),避免在业务代码里直接 new 具体类型。
关键点不是“多高级”,而是“不暴露 new、不硬编码类型、能统一管理生命周期”。下面是最常用且安全的做法:
#include#include #include class Product { public: virtual ~Product() = default; virtual void operation() const = 0; };
class ConcreteProductA : public Product { public: void operation() const override { / ... / } };
class ConcreteProductB : public Product { public: void operation() const override { / ... / } };
class SimpleFactory { public: static std::unique_ptr
create(const std::string& type) { if (type == "A") { return std::make_unique (); } else if (type == "B") { return std::make_unique (); } else { throw std::invalid_argument("Unknown product type: " + type); } } };
使用时只需:auto p = SimpleFactory::create("A"); —— 调用方完全不知道 ConcreteProductA 的存在,也不负责 delete。
std::unique_ptr 是首选:语义清晰(独占所有权)、无引用计数开销Product*):容易引发内存泄漏或误删const std::string& 而非 const char*:避免空指针和编码歧义
安全的场景字符串判断在编译期不可检查,运行时才报错。如果产品类型固定且数量少,用 enum 更可靠:
enum class ProductType { A, B };
class SimpleFactory {
public:
static std::unique_ptr create(ProductType type) {
switch (type) {
case ProductType::A: return std::make_unique();
case ProductType::B: return std::make_unique();
default: throw std::invalid_argument("Unknown enum value");
}
}
};
好处是显而易见的:
-Wswitch-enum 或 /we4061)这是 C++ 工厂模式中最隐蔽也最致命的问题。如果基类 Product 的析构函数不是 virtual,那么通过 Product* 或 std::unique_ptr 删除对象时,ConcreteProductA 的析构函数根本不会被调用 —— 导致资源泄漏(比如文件句柄、内存池分配的内存等)。
务必确认:
Product 类中声明了 virtual ~Product() = default;(或自定义虚析构函数)virtual
工厂本身不复杂,难的是让整个继承链和生命周期管理真正安全。一旦漏掉虚析构,调试起来往往表现为“看起来正常,但内存缓慢增长”或“析构时崩溃”,而且问题不在工厂代码里,而在使用者对多态销毁的理解上。