工厂模式、多态与接口设计
工厂模式、多态与接口设计
时间:2026/04/09
关键词:抽象接口、虚函数、工厂函数、依赖倒置、
override、虚析构、unique_ptr
核心目标:理解什么时候该把“创建对象”和“使用对象”分开。
1. 为什么需要工厂模式
很多代码的问题不是“不会 new”,而是:
- 调用方知道太多具体类型
- 构造逻辑散落各处
- 后续替换实现很痛苦
工厂模式的核心价值是:
- 把对象创建逻辑集中起来
- 让调用方依赖抽象接口,而不是具体实现
2. 多态接口的基础
1 | struct Pet { |
这里要点有两个:
- 基类析构函数要么虚,要么不允许多态删除
- 派生类重写时用
override
3. 一个最简单的工厂函数
1 |
|
调用方只关心:
- 我要一个
Pet
而不关心:
- 具体怎么构造
Cat/Dog
4. 为什么返回 unique_ptr
返回裸指针会引入一个问题:
- 谁负责
delete
用 std::unique_ptr 更清晰:
- 工厂负责创建
- 调用方接管独占所有权
这是现代 C++ 工厂接口最常见的实践。
5. 简单工厂 vs 工厂方法
5.1 简单工厂
一个集中函数,根据参数分支创建对象。
优点:
- 简单直接
缺点:
- 新增类型时可能要改原工厂
5.2 工厂方法
把“创建哪种对象”交给子类。
适合:
- 框架式扩展
- 产品族较复杂
但对小项目来说,简单工厂已经够用。
6. 接口设计比模式名更重要
真正工程里,更该关注这些问题:
- 基类是不是表达了稳定抽象
- 调用方是否真的不需要知道具体类型
- 返回所有权是否清晰
- 是否需要注册表或插件化
很多时候模式本身不复杂,难的是接口边界。
7. 一个更贴近工程的例子
1 | struct Reducer { |
这里“算法骨架”不变,“聚合策略”可替换。
这类设计常和工厂、策略模式一起出现。
8. 工厂模式的常见扩展
8.1 注册表工厂
把字符串或类型 id 映射到创建函数:
- 更适合插件化
- 更适合可扩展系统
8.2 抽象工厂
如果你需要创建一整组关联对象,就可能进入抽象工厂场景。
例如:
- UI 皮肤
- 跨平台组件族
9. 常见坑
9.1 基类没有虚析构
多态删除会出问题。
9.2 工厂返回裸指针
所有权不清晰。
9.3 为了“用模式而用模式”
小项目里过度抽象只会增加复杂度。
9.4 基类接口设计得太宽
会让派生类被迫实现很多并不需要的东西。
10. 一页总结
工厂模式最核心的收益不是“设计模式名词”,而是:
- 创建逻辑集中
- 调用方依赖抽象
- 所有权表达清晰
如果只记一句:
当“对象怎么创建”开始影响“对象怎么使用”时,就该考虑把创建逻辑抽出来。