建造者模式解决的是"构造一个参数又多、又有可选参数的复杂对象"的痛点,Lombok 的 @Builder、StringBuilder、OkHttp 的 Request.Builder 都是它。这篇把它讲清楚:它和工厂模式的区别在哪、链式调用怎么来的。
一、解决什么问题
当一个对象的构造参数很多、又有可选参数时,传统的构造函数会变得很难用:
java
// 痛点:参数多、顺序难记、可选参数要用 null 占位
Computer c = new Computer("i7", "16G", "512G", null, null, true, null, "NVIDIA");
// ↑ 第4、5个参数是啥?传 null 是为了占位?可读性极差三个痛点:
- 参数多、顺序难记:8 个参数谁记得清第几个是啥
- 可选参数要用 null 占位:不想设置的参数也得传个
null - 重载构造函数爆炸:不同参数组合要写一堆重载构造函数
建造者模式用链式调用解决:想设哪个设哪个,参数名见名知意,可选参数直接不调。
二、建造者模式怎么落地
java
public class Computer {
private String cpu;
private String memory;
private String disk;
private String gpu; // 可选
private Computer(Builder builder) { // 私有构造,只让 Builder 建
this.cpu = builder.cpu;
this.memory = builder.memory;
this.disk = builder.disk;
this.gpu = builder.gpu;
}
// 建造者内部类
public static class Builder {
private String cpu;
private String memory;
private String disk;
private String gpu;
public Builder cpu(String cpu) { this.cpu = cpu; return this; } // 返回 this 实现链式
public Builder memory(String m) { this.memory = m; return this; }
public Builder disk(String d) { this.disk = d; return this; }
public Builder gpu(String g) { this.gpu = g; return this; }
public Computer build() { return new Computer(this); } // 最终构建
}
}
// 使用:链式调用,见名知意,可选参数直接不写
Computer c = new Computer.Builder()
.cpu("i7")
.memory("16G")
.disk("512G")
.gpu("NVIDIA") // 可选,不写就不设
.build();核心两点:
- Builder 的每个 setter 返回
this——这是"链式调用"的来源 build()方法最后调用私有构造,产出目标对象
三、Lombok @Builder 一行搞定
手写 Builder 很啰嗦,实际项目都用 Lombok:
java
@Builder
public class Computer {
private String cpu;
private String memory;
private String disk;
private String gpu;
}
// 用法和手写完全一样
Computer c = Computer.builder().cpu("i7").memory("16G").build();@Builder 编译时自动生成上面的 Builder 内部类,一行注解省掉几十行样板代码。
四、建造者 vs 工厂(易混)
两者都是创建型、都是"不直接 new",但关注点不同:
| 维度 | 工厂模式 | 建造者模式 |
|---|---|---|
| 关注 | 创建哪个对象(选型) | 创建这个对象的复杂组装(步骤) |
| 参数 | 通常参数简单 | 参数多、有可选 |
| 典型 | PayFactory.create("alipay") | Computer.builder().cpu().memory().build() |
一句话:工厂管"选谁造",建造者管"怎么一步步组装"。一个对象参数多、有可选参数,就用建造者;要屏蔽"具体创建哪个子类",用工厂。工厂模式的详解见《工厂模式》。
小结
- 建造者解决"参数多 + 可选参数"的构造痛点,核心是链式调用
- Builder 的 setter 返回
this实现链式,build()最终产出对象 - Lombok
@Builder一行注解自动生成 Builder - 与工厂区别:工厂"选谁造",建造者"怎么组装"
下一步可以看同为创建型的《原型模式》——它和建造者/工厂不同,是"复制一个已有对象"而不是"从零构建"(文章整理中)。
