第2章:工厂方法模式在核心对象创建中的应用
章节边界与分层定位
本章聚焦于工厂方法模式在Framework层对象创建场景中的架构应用。边界限定于:工厂接口的抽象契约、多产品族的并行管理、以及延迟创建与资源控制的权衡。不涵盖简单工厂或抽象工厂的完整讨论,仅在对比表中提及。
在分层中,工厂方法模式处于抽象层与具体实现层之间的桥梁位置:
- 上层依赖:框架核心(如对象管理器、上下文容器)通过工厂接口请求对象,不感知具体类。
- 下层实现:具体工厂负责实例化,可跨产品族共享同一创建协议。
组件职责与信任链路
| 组件 | 职责 | 信任条件 |
|---|---|---|
| 工厂接口(Creator) | 声明创建方法(如 createProduct()),定义返回类型。 | 接口稳定、不随具体产品变更。 |
| 具体工厂(ConcreteCreator) | 实现创建方法,决定实例化哪个具体产品类。 | 与具体产品类之间硬依赖可被接受。 |
| 抽象产品(Product) | 定义产品行为契约。 | 接口纯抽象,无具体耦合。 |
| 具体产品(ConcreteProduct) | 实现产品行为。 | 与具体工厂之间无直接控制链路。 |
信任链路:调用方 → 工厂接口(信赖契约) → 具体工厂(信赖能按契约创建) → 具体产品(信赖符合行为)。核心是接口契约而非具体类的信任传递。
数据流与控制流
- 控制流:调用方传递上下文参数 → 工厂接口方法 → 具体工厂根据上下文(如配置、环境变量)选择具体产品 → 返回产品实例。
- 数据流:调用方仅获得产品接口引用;内部创建细节(如参数组装、资源分配)对调用方完全隔离。
产品族管理策略
当存在多个关联产品族(如不同协议/平台/版本)时,工厂方法模式通过多具体工厂组合实现产品族管理:
- 为每个产品族定义一个具体工厂类。
- 各具体工厂共享同一工厂接口,返回类型为抽象产品。
- 运行时通过策略选择具体工厂(如通过配置文件、注册表实现)。
常见风险:产品族扩张导致具体工厂数量增长,需配合工厂缓存池或动态类加载控制复杂度。
架构提示:产品族管理的本质是将“创建对象”的职责从客户端剥离,交给独立工厂层级。这一分离也是控制反转(IoC)在创建侧的典型体现。
延迟创建权衡分析
| 维度 | 延迟创建的收益 | 延迟创建的代价 |
|---|---|---|
| 资源占用 | 避免启动时实例化全部产品族,减少内存和句柄消耗。 | 首次访问时存在“冷启动延迟”,影响响应速度。 |
| 启动速度 | 框架初始化更快,用户感知更流畅。 | 后续运行时可能出现突发性能抖动。 |
| 配置灵活性 | 允许运行时动态决定创建哪个具体工厂(如根据用户权限)。 | 工厂工厂的选择逻辑可能增加复杂度。 |
| 错误暴露时机 | 无效配置仅在首次创建时报错,容错性更好。 | 错误风险从启动期推迟到运行期,难以提前验证。 |
选型权衡:对于高频创建且有严格延迟要求的场景(如UI框架的View对象),建议配合预创建缓存+延迟创建混合策略;对于低频批量创建(如网络连接池对象),优先使用延迟创建以降低闲时资源开销。
落地步骤
- 定义抽象产品接口:列出所有业务方法,保证纯虚。
- 实现具体产品:每个产品族至少一个实现类。
- 设计工厂接口:声明
createProduct(Params)方法,返回抽象产品引用。 - 编写具体工厂:每个产品族一个工厂类,内部实现实例化逻辑。
- 建立工厂选择器:通常是静态方法或配置驱动映射,能根据上下文返回对应具体工厂实例。
- 集成延迟创建:在工厂内部加入“按需创建”判断,如
if (instance == null) { instance = new ConcreteProduct(); }。
代码示例(伪Java风格,仅展示延迟创建逻辑):
public class LazyConcreteFactory extends ProductFactory {
private Product instance = null;
@Override
public Product createProduct() {
if (instance == null) {
instance = new ConcreteProductA();
// 初始化资源
instance.init();
}
return instance;
}
}
验收标准
- 接口隔离:客户端代码中不存在任何
new ConcreteProduct字样。 - 产品族可扩展:新增产品族只需增加具体工厂和具体产品类,无需修改现有工厂接口。
- 延迟创建正确:在首次调用前,目标工厂未持有产品对象的引用(通过单元测试验证内存图)。
- 信任链路独立:替换某个具体工厂实现时,不影响其他产品族的创建链路。
- 性能合规:延迟创建的首次创建时间 ≤ 模块约定的P99响应时限。