不能直接new具体类,因其将创建逻辑硬编码进业务代码,导致换实现、加类型或mock测试时需全局修改;工厂模式通过集中管理new操作、返回std::unique_ptr并依赖抽象接口,实现解耦与安全。

为什么不能直接 new 具体类
当你在业务逻辑里写 new ConcreteProductA(),就等于把创建细节硬编码进调用方——后续换实现、加新类型、做 mock 测试,全得改业务代码。简单工厂模式的核心目的不是“多写一个类”,而是让 new 这个动作只出现在一个可控的、集中管理的地方。
接口抽象的关键在于:调用方只依赖 Product* 或 std::unique_ptr<product></product>,完全不知道背后是 A 还是 B;而工厂内部才负责 new ConcreteProductA 这类具体操作。
工厂函数该返回 raw pointer 还是智能指针
返回 std::unique_ptr<product></product> 是更安全的选择。裸指针(Product*)容易引发内存泄漏或误 delete,尤其在异常路径下。但要注意:如果工厂返回的是栈对象地址(比如返回局部对象引用),那无论用什么指针都崩溃。
- ✅ 推荐:返回
std::unique_ptr<product></product>,调用方无需关心释放 - ⚠️ 慎用:返回
Product*,必须明确约定所有权归属(通常工厂不移交所有权,那就别这么干) - ❌ 错误:返回局部对象的引用或指针,例如
return &local_obj;
示例工厂函数签名:
std::unique_ptr<product> createProduct(ProductType type);</product>
如何避免 if-else 链膨胀成维护噩梦
当产品类型超过 4–5 种,硬写 if (type == A) { return std::make_unique<a>(); }</a> 就开始反人类了。此时应该用静态映射表替代分支判断。
- 用
std::unordered_map存ProductType → std::function<:unique_ptr>()></:unique_ptr> - 注册逻辑放在类外或静态初始化块中,避免每次调用都重建映射
- 注意 C++17 起支持内联变量,可安全定义静态 map
关键点:注册和查找分离,新增类型只需加一行注册,不碰原有逻辑。
继承体系里 virtual 析构函数漏写会怎样
如果基类 Product 的析构函数不是 virtual,而你通过 Product* 或 std::unique_ptr<product></product> 删除子类对象,只会调用基类析构函数——子类成员变量、资源(如文件句柄、堆内存)不会被清理,导致未定义行为或泄漏。
务必这样写:
class Product {
public:
virtual ~Product() = default; // 必须有 virtual
virtual void operation() = 0;
};
这是 C++ 多态销毁的铁律,跟工厂无关,但工厂返回多态对象时,这个坑踩一次就够项目延期一周。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











