> 技术文档 > Java设计模式-建造者模式

Java设计模式-建造者模式


一句话记住
“把复杂对象拆成 字段-填充-组装 三个阶段,先指挥 Builder 按序 一步步建造,最后 一次性交付 一个 完整且不可变 的对象。”

一、为什么要用建造者模式?

设想你要组装一台“高配台式机”:

  • 机箱型号?CPU 型号?显卡?主板?电源?RGB?
  • 参数多、排列组合爆炸 → 构造器重载成几十种?
  • 必填与选填混杂,部分字段有顺序依赖 → 容易写出残次品对象。
  • 对象创建完应是不可变(Immutability),不允许二次 setXXX。

传统方案:

// 错误示范:重叠构造器 Telescoping ConstructorComputer c1 = new Computer(\"NZXT\", \"AMD 7950X\", null, null, null,null, null); // 错填Computer c2 = new Computer(\"ABCD\", \"Intel 13900K\",\"ASUS\",\"RTX4090\",null,null, \"Seasonic 850W\");

建造者方案:

Computer pc = Computer.builder() .cpu(\"AMD Ryzen 9 7950X\") .gpu(\"RTX 4090\") .ram(\"32G DDR5\") .build();

优点:

  • 可读性极高,接近自然语言 DSL。
  • 可选字段“不填也不会传 null”。
  • 复杂校验全部隐藏在 build() 里。
  • 生成的 Computer 无 setter,线程安全。

二、四种实现方式

版本 场景 JDK 支持 不可变 样板代码 传统 Builder 类 所有 JDK 自写 ✅ 多 链式 setter 仅可变性要求低 自写 ❌ 极少 Lombok @Builder 任何 >= 1.8 Lombok 插件 ✅ 极少 Java 14+ record + Builder Java ≥ 14 语言支持 ✅ 中

下面详细演示前两种,后两种给出关键代码片段。

三、传统 Builder 实现

1) 产品(Product)

public final class Computer { // 必传 private final String cpu; // 可选 private final String gpu; private final int ram; private final Storage storage; private final boolean hasRGB; // 私有 ctor:只能是 Builder 调用 private Computer(Builder b) { this.cpu = b.cpu; this.gpu = b.gpu; this.ram = b.ram; this.storage = b.storage; this.hasRGB = b.hasRGB; } public static Builder builder() { return new Builder(); } @Override public String toString() { return \"Computer{cpu=\" + cpu + \", gpu=\" + gpu + \", ram=\" + ram + \"G}\"; } // ========= Builder 内部类 ========= public static class Builder { // 必填字段在 Builder 中仍须初始 dummy,或 build 时检查 private String cpu; // 非 null private String gpu; private int ram = 8; // 默认值 private Storage storage = new Storage(\"SSD\", 512); private boolean hasRGB; public Builder cpu(String cpu) { this.cpu = cpu; return this; // 链式 } public Builder gpu(String gpu) { this.gpu = gpu; return this; } public Builder ram(int ram) { this.ram = ram; return this; } public Builder storage(String type, int size) { this.storage = new Storage(type, size); return this; } public Builder rgb(boolean flag) { this.hasRGB = flag; return this; } // 集中校验 public Computer build() { Objects.requireNonNull(cpu, \"CPU must not be null\"); if (ram < 4) throw new IllegalArgumentException(\"ram invalid\"); return new Computer(this); } }}

2) 客户端代码

Computer pc = Computer.builder() .cpu(\"Intel i9-14900K\") .ram(64) .storage(\"PCIe4 NVMe\", 2048) .gpu(\"RTX 4090\") .rgb(true) .build();System.out.println(pc);

四、Lombok 极简版本

只需一个注解:

@Builder(toBuilder = true)@Value // = Immutable + getter + equals/hash/toStringpublic class Computer { String cpu; String gpu; int ram; Storage storage; boolean hasRGB;}Computer pc = Computer.builder().cpu(\"Ryzen\").build();

@Value 生成的类 final,所有字段 final,无 setter,builder() 方法自动提供。

五、Java 14+ record + Builder

record 天生不可变,但缺少默认的 Builder。可手写一次,复用多次:

public record Computer(String cpu, String gpu, int ram, Storage storage, boolean hasRGB) { public static class Builder { // 省略同上 }}

六、与相近模式比较

  • 抽象工厂:返回 一组 相关对象(ProductA, ProductB),而 Builder 一步步构造一个复杂对象
  • 工厂方法:解决“哪种类来实例化”,Builder 解决“如何用复杂步骤拼好这个实例”。
  • 原型模式:通过克隆创建,Builder 是 从零建造
  • 装饰者:动态包装附加行为,Builder 静态地把字段锁定在构造期。

七、最佳实践小结

  1. 字段数 ≥ 4,且参数可选 → 优先考虑 Builder。
  2. 线程安全 → build() 之后对象不可变。
  3. Spring Boot @ConfigurationProperties 绑定支持 Builder:@ConstructorBinding + @Builder(Spring 2.2+)。
  4. 序列化 → 加 @Jacksonized(Lombok 1.18.14+)让 Jackson 也能用 Builder 反序列化 JSON。
  5. 分层架构 → Dozer / MapStruct 可自动从 DTO → Builder → Entity。

记住口诀:
多参构造真痛苦,建造者模式来相助;链式调用表义明,一敲 build 对象成。