iBoxHub技术日志

怀念我们的昨天,憧憬我们的明天,珍惜我们的今天

创建型模式

创建型设计模式

——对象诞生的控制权与系统稳定性


一、为什么需要创建型模式(第一性原理)

在软件系统中,对象的创建并不是一个“语法问题”,而是一个架构控制问题

创建型模式解决的核心不是“如何 new 对象”, 而是:谁来控制对象的诞生方式、创建时机与生命周期?

当系统规模扩大,对象创建会暴露出三个根本性风险:

  1. 变化失控
    • 产品类型变化
    • 构造过程变化
    • 内部结构变化
  2. 复杂性泄漏
    • 构造参数过多
    • 校验逻辑分散
    • 对象可能处于非法状态
  3. 生命周期失序
    • 全局对象泛滥
    • 隐式依赖
    • 并发与销毁问题

👉 创建型模式的本质目标

将“对象如何诞生”的不稳定性,从业务逻辑中隔离出来, 并集中到可治理、可演进的位置。


二、创建型模式的稳定抽象框架

从原理层看,所有创建型模式都在回答同一组问题:

维度核心问题
创建时机立即创建?延迟创建?按需创建?
创建复杂度一步完成?多步构造?复制生成?
生命周期短生命周期?长生命周期?全局唯一?
变化来源类型变化?结构变化?产品族变化?

不同模式 = 对这些变量的不同控制策略


三、构建复杂对象: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生命周期全局状态