创建型设计模式
——对象诞生的控制权与系统稳定性
一、为什么需要创建型模式(第一性原理)
在软件系统中,对象的创建并不是一个“语法问题”,而是一个架构控制问题。
创建型模式解决的核心不是“如何 new 对象”, 而是:谁来控制对象的诞生方式、创建时机与生命周期?
当系统规模扩大,对象创建会暴露出三个根本性风险:
- 变化失控
- 产品类型变化
- 构造过程变化
- 内部结构变化
- 复杂性泄漏
- 构造参数过多
- 校验逻辑分散
- 对象可能处于非法状态
- 生命周期失序
- 全局对象泛滥
- 隐式依赖
- 并发与销毁问题
👉 创建型模式的本质目标:
将“对象如何诞生”的不稳定性,从业务逻辑中隔离出来, 并集中到可治理、可演进的位置。
二、创建型模式的稳定抽象框架
从原理层看,所有创建型模式都在回答同一组问题:
| 维度 | 核心问题 |
|---|---|
| 创建时机 | 立即创建?延迟创建?按需创建? |
| 创建复杂度 | 一步完成?多步构造?复制生成? |
| 生命周期 | 短生命周期?长生命周期?全局唯一? |
| 变化来源 | 类型变化?结构变化?产品族变化? |
不同模式 = 对这些变量的不同控制策略
三、构建复杂对象:Builder(建造者)
1. 设计动机(原理层)
当一个对象的创建:
- 构造参数过多
- 参数之间存在约束关系
- 构造步骤有顺序与组合变化
- 对象希望保持不可变
此时,“构造函数”已不再是合适的抽象。
Builder 的本质: 将“构建过程”从“最终表示”中剥离出来
2. 核心思想(架构层)
Builder 引入三个角色分离关注点:
| 角色 | 责任 |
|---|---|
| Builder | 定义构建步骤 |
| ConcreteBuilder | 实现具体构建细节 |
| Director | 控制构建顺序 |
👉 控制权变化: 对象不再“被一次性构造”,而是“被过程性组装”。
3. Builder 解决的不是“复杂”,而是“可变复杂”
Builder 适用于:
- 构建步骤 ≥ 3
- 步骤顺序可能变化
- 同一过程生成不同表示
而不适用于:
- 简单 DTO
- 结构稳定、无约束的对象
4. 工程示例(实现层)
interface Builder {
Builder process1();
Builder process2();
Builder process3();
Product build();
}
Director 将构建逻辑集中:
public Product constructProduct(Builder builder){
builder.process1();
builder.process2();
builder.process3();
return builder.build();
}
四、封装“类型变化”:工厂体系
1. 工厂模式的统一抽象
工厂模式的本质不是“替你 new”, 而是:将“产品类型变化”从使用方隔离出去
2. 简单工厂:集中决策(但不可扩展)
- 优点:
- 使用方无需关心具体类
- 根本问题:
- 决策逻辑集中
- 违反开闭原则
👉 适合小系统,不适合演进型系统
3. 工厂方法:延迟实例化到子类
将“创建哪个产品”的决策权,下放到子类
核心思想:
- 父类定义使用流程
- 子类决定具体产品
这使得:
- 新产品通过新增子类完成
- 原有逻辑无需修改
👉 工厂方法本质上是一种 “创建逻辑的多态化”
4. 抽象工厂:控制产品族一致性
抽象工厂解决的是更高阶的问题:
不是“创建一个产品”, 而是“创建一组相互依赖、风格一致的产品”
典型场景:
- UI 组件族
- 跨平台适配
- 数据库驱动族
⚠️ 代价:
- 扩展产品族容易
- 扩展产品种类困难
5. 工厂体系的稳定认知总结
| 模式 | 控制的变化 |
|---|---|
| 简单工厂 | 创建参数 |
| 工厂方法 | 产品类型 |
| 抽象工厂 | 产品族一致性 |
五、复制而非构造:Prototype(原型)
1. 原理动机
当对象:
- 创建成本高
- 同类对象差异小
- 构建步骤复杂但稳定
此时,“重新构建”是一种浪费。
原型模式的核心思想: 用已有实例作为创建模板
2. Prototype 的真正价值
- 运行期动态改变对象种类
- 快速生成配置化对象
- 避免复杂构造链
但其风险在于:
- 深拷贝成本
- 状态一致性
- 引用对象共享问题
3. 工程实现要点
@Override
protected Object clone() throws CloneNotSupportedException {
Product product = (Product) super.clone();
product.part1 = (Part1) part1.clone();
return product;
}
👉 原型的难点不在 clone,而在“复制语义是否正确”
六、全局唯一与生命周期治理:Singleton
1. Singleton 的真实定位
Singleton 解决的不是“创建问题”, 而是**“全局生命周期失控问题”**
它本质上是一种:
- 生命周期管理手段
- 全局访问策略
2. 单例的工程实现方式(实现层)
- 饿汉式:简单、安全,但无延迟加载
- 懒汉式:需处理并发
- 静态内部类:推荐方案
- 枚举:JVM 级保障
- 双重检查锁:并发优化方案
这些都是实现策略,而非设计本身。
3. Singleton 的系统性问题(原理层)
- 隐藏依赖关系
- 破坏可测试性
- 引入全局状态
- 阻碍演进为多实例
👉 Singleton 往往是“阶段性方案”,而非终局设计
4. 演进路径
Singleton
↓
Factory + 配置
↓
DI 容器
↓
显式生命周期管理
七、创建型模式的统一对照(稳定知识)
| 模式 | 核心控制点 | 主要代价 |
|---|---|---|
| Builder | 构建过程 | 引入额外对象 |
| Factory Method | 产品类型 | 类数量增加 |
| Abstract Factory | 产品族 | 扩展受限 |
| Prototype | 创建成本 | 拷贝复杂 |
| Singleton | 生命周期 | 全局状态 |