C++ 工厂方法模式
一、模式简介
工厂方法模式(Factory Method Pattern)是创建型设计模式的核心成员,其核心思想是:定义一个创建对象的接口(抽象工厂),但由子类(具体工厂)决定实例化哪个类(具体产品)。通过这种设计,将对象的创建逻辑与使用逻辑彻底分离,让代码更具扩展性和可维护性。
二、核心概念与结构
工厂方法模式包含 4 个关键角色,形成清晰的继承体系:
抽象产品(Abstract Product)
定义产品的通用接口,所有具体产品都需实现该接口。例如 “交通工具” 抽象类,包含 “行驶” 纯虚函数。
具体产品(Concrete Product)
抽象产品的实现类,是工厂方法最终创建的对象。例如 “汽车”“自行车” 类,分别实现 “行驶” 方法。
抽象工厂(Abstract Factory)
定义创建产品的接口(工厂方法),返回抽象产品类型。例如 “交通工具工厂” 抽象类,包含 “创建交通工具” 纯虚函数。
具体工厂(Concrete Factory)
抽象工厂的实现类,重写工厂方法,返回具体产品实例。例如 “汽车工厂” 创建汽车对象,“自行车工厂” 创建自行车对象。
三、代码示例
1 | #include <iostream> |
输出结果:汽车:百公里加速5秒
四、与简单工厂模式的对比
简单工厂模式(Simple Factory Pattern)虽然不属于 GoF 23 种设计模式,但也是常用的对象创建方案。它通过一个工厂类的静态方法,根据传入参数决定创建哪个具体产品。两种模式的主要差异如下:
对比维度 | 工厂方法模式 | 简单工厂模式 |
---|---|---|
核心设计 | 通过抽象工厂类定义创建接口,由子类实现具体创建逻辑 | 单一工厂类包含所有创建逻辑,使用条件语句(如 if-else)选择产品 |
扩展性 | 符合 “开闭原则”,新增产品只需添加具体产品和工厂类 | 新增产品需修改工厂类的创建逻辑(添加新的条件分支),违背 “开闭原则” |
灵活性 | 支持多态调用,同一调用逻辑可适配不同具体工厂 | 调用者需传入具体产品标识,无法实现多态切换产品类型 |
代码复杂度 | 类数量较多,适合复杂、需频繁扩展的场景 | 代码简洁,适合产品类型固定、创建逻辑简单的场景 |
应用场景 | 框架设计、插件系统等需要高度扩展性的场景 | 业务初期快速开发,或产品类型较少且稳定的场景 |
例如,在日志系统中,若未来可能扩展 “文件日志”“控制台日志”“网络日志” 等多种类型,工厂方法模式更合适;若仅需区分 “普通日志” 和 “错误日志” 两种固定类型,简单工厂模式能以更少代码量实现。
五、应用场景
当代码满足以下条件时,优先使用工厂方法模式:
不确定具体产品类型:例如框架开发中,无法预知用户会扩展哪些产品(如插件系统)。
需要统一创建逻辑:多个产品的创建有共性流程(如初始化配置、权限校验),可在抽象工厂中封装。
希望解耦创建与使用:调用者只需知道抽象产品接口,无需关心具体实现(如日志系统,无需区分 “文件日志” 还是 “控制台日志”)。
六、优缺点分析
优点 | 缺点 |
---|---|
1. 符合 “开闭原则”:新增产品时,只需添加具体产品和具体工厂,无需修改原有代码 | 1. 类数量增加:每新增一个产品,需对应新增一个具体工厂类,增加代码复杂度 |
2. 依赖抽象而非具体:调用者依赖抽象产品和工厂,降低代码耦合度 | 2. 理解成本提升:相比直接 new 对象,需要理解抽象与子类的继承关系 |
3. 利用多态特性:同一调用逻辑可适配不同产品,代码更灵活 | 3. 简单场景冗余:若产品类型固定且无需扩展,使用工厂方法会显得冗余 |