一、引言
建造者模式(Builder Pattern)是一种创建型设计模式,它将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
核心问题
在日常开发中,我们经常需要创建包含多个组成部分的复杂对象,比如:
- 电脑(CPU、内存、硬盘、显卡等)
- 汽车(发动机、轮胎、座椅、车身等)
- SQL查询(SELECT、FROM、WHERE、GROUP BY等)
如果使用传统的构造函数或setter方法创建这些对象,会遇到以下问题:
- 构造函数参数过多:当对象包含很多可选参数时,构造函数会变得臃肿且难以维护
- 参数顺序混乱:容易记错参数顺序,导致错误
- 不可变对象构建困难:难以保持对象的不可变性
- 构建逻辑耦合:对象的创建逻辑与业务逻辑混在一起
应用场景
建造者模式主要适用于以下场景:
二、核心结构
建造者模式包含四个核心角色:
┌─────────────────────────────────────────────────────────┐
│ 指挥者 │
│ Director │
│ + construct() │
└────────────────┬────────────────────────────────────────┘
│
│ 指挥构建流程
↓
┌─────────────────────────────────────────────────────────┐
│ 抽象建造者 │
│ Builder │
│ + buildPartA() │
│ + buildPartB() │
│ + getResult() │
└────────────────┬────────────────────────────────────────┘
│
│ 继承/实现
┌────────┴────────┐
↓ ↓
┌──────────────┐ ┌──────────────┐
│ 具体建造者A │ │ 具体建造者B │
│ ConcreteBuilder│ │ ConcreteBuilder│
│ + buildPartA() │ │ + buildPartA() │
│ + buildPartB() │ │ + buildPartB() │
│ + getResult() │ │ + getResult() │
└──────┬───────┘ └──────┬───────┘
│ │
│ 构建 │ 构建
↓ ↓
┌──────────────┐ ┌──────────────┐
│ 产品A │ │ 产品B │
│ Product │ │ Product │
└──────────────┘ └──────────────┘
角色说明
| 产品(Product) | 最终要构建的复杂对象 | 包含多个组成部分,通常使用setter方法设置属性 |
| 抽象建造者(Builder) | 抽象接口或抽象类 | 定义创建产品各个部件的抽象方法 |
| 具体建造者(ConcreteBuilder) | 实现Builder接口 | 实现构建各个部件的具体逻辑,返回最终产品 |
| 指挥者(Director) | 指挥构建过程 | 按照特定顺序调用Builder的方法来构建产品 |
关系说明
- 产品是最终构建的目标对象
- 抽象建造者定义了构建产品的抽象接口
- 具体建造者实现了具体的构建逻辑
- 指挥者控制构建的流程和顺序,但不直接参与构建
三、实现步骤
下面通过一个电脑组装的完整示例来演示建造者模式的实现:
1. 定义产品类
/**
* 产品类:电脑
*/
public class Computer {
// 必需参数
private String cpu;
private String ram;
// 可选参数
private String storage;
private String graphicsCard;
private String operatingSystem;
private String monitor;
// 私有构造方法,只能通过Builder创建
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
this.graphicsCard = builder.graphicsCard;
this.operatingSystem = builder.operatingSystem;
this.monitor = builder.monitor;
}
// Getter方法
public String getCpu() { return cpu; }
public String getRam() { return ram; }
public String getStorage() { return storage; }
public String getGraphicsCard() { return graphicsCard; }
public String getOperatingSystem() { return operatingSystem; }
public String getMonitor() { return monitor; }
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\\'' +
", ram='" + ram + '\\'' +
", storage='" + storage + '\\'' +
", graphicsCard='" + graphicsCard + '\\'' +
", operatingSystem='" + operatingSystem + '\\'' +
", monitor='" + monitor + '\\'' +
'}';
}
/**
* 静态内部类:Builder
*/
public static class Builder {
// 必需参数
private final String cpu;
private final String ram;
// 可选参数 – 初始化为默认值
private String storage = "256GB SSD";
private String graphicsCard = "Integrated Graphics";
private String operatingSystem = "Windows 11";
private String monitor = "24 inch LCD";
// 构造方法:必需参数
public Builder(String cpu, String ram) {
this.cpu = cpu;
this.ram = ram;
}
// 链式调用设置可选参数
public Builder storage(String storage) {
this.storage = storage;
return this;
}
public Builder graphicsCard(String graphicsCard) {
this.graphicsCard = graphicsCard;
return this;
}
public Builder operatingSystem(String operatingSystem) {
this.operatingSystem = operatingSystem;
return this;
}
public Builder monitor(String monitor) {
this.monitor = monitor;
return this;
}
// 构建最终产品
public Computer build() {
// 参数校验
if (cpu == null || cpu.isEmpty()) {
throw new IllegalArgumentException("CPU cannot be empty");
}
if (ram == null || ram.isEmpty()) {
throw new IllegalArgumentException("RAM cannot be empty");
}
return new Computer(this);
}
}
}
2. 使用示例
/**
* 测试类
*/
public class BuilderPatternDemo {
public static void main(String[] args) {
// 场景1:构建基础配置的电脑
Computer basicComputer = new Computer.Builder(
"Intel i5", "16GB"
).build();
System.out.println("基础配置电脑:");
System.out.println(basicComputer);
System.out.println();
// 场景2:构建游戏电脑(链式调用)
Computer gamingComputer = new Computer.Builder(
"Intel i9", "32GB"
).storage("1TB NVMe SSD")
.graphicsCard("NVIDIA RTX 4090")
.operatingSystem("Windows 11 Pro")
.monitor("27 inch 4K IPS")
.build();
System.out.println("游戏配置电脑:");
System.out.println(gamingComputer);
System.out.println();
// 场景3:构建办公电脑
Computer officeComputer = new Computer.Builder(
"AMD Ryzen 5", "8GB"
).storage("512GB SSD")
.graphicsCard("AMD Radeon Graphics")
.operatingSystem("Ubuntu 22.04")
.build();
System.out.println("办公配置电脑:");
System.out.println(officeComputer);
}
}
3. 输出结果
基础配置电脑:
Computer{cpu='Intel i5', ram='16GB', storage='256GB SSD',
graphicsCard='Integrated Graphics', operatingSystem='Windows 11',
monitor='24 inch LCD'}
游戏配置电脑:
Computer{cpu='Intel i9', ram='32GB', storage='1TB NVMe SSD',
graphicsCard='NVIDIA RTX 4090', operatingSystem='Windows 11 Pro',
monitor='27 inch 4K IPS'}
办公配置电脑:
Computer{cpu='AMD Ryzen 5', ram='8GB', storage='512GB SSD',
graphicsCard='AMD Radeon Graphics', operatingSystem='Ubuntu 22.04',
monitor='24 inch LCD'}
四、优缺点分析
优点
| 解耦构建与表示 | 将复杂对象的构建过程与表示分离,相同的构建过程可以创建不同的表示 |
| 代码可读性强 | 链式调用让代码更清晰,易于理解对象的创建过程 |
| 支持可选参数 | 优雅地解决构造函数参数过多的问题,支持可选参数 |
| 保证不可变性 | 通过私有构造器和final字段,可以轻松创建不可变对象 |
| 灵活构建 | 可以逐步构建对象,支持不同的构建组合 |
| 易于扩展 | 新增具体建造者无需修改现有代码,符合开闭原则 |
缺点
| 代码量增加 | 需要创建Builder类,代码量相对增加 |
| 性能开销 | 创建对象时需要先创建Builder,会有轻微性能影响 |
| 适用范围受限 | 仅适用于复杂对象的创建,简单对象使用会显得过度设计 |
五、应用场景
1. 典型应用场景
// 场景1:StringBuilder – JDK中的经典应用
StringBuilder sb = new StringBuilder()
.append("Hello")
.append(" ")
.append("World")
.append("!")
.toString();
// 场景2:AlertDialog.Builder – Android开发
new AlertDialog.Builder(context)
.setTitle("提示")
.setMessage("确定要删除吗?")
.setPositiveButton("确定", (dialog, which) -> {})
.setNegativeButton("取消", (dialog, which) -> {})
.show();
// 场景3:OkHttpClient – 网络请求
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor())
.build();
// 场景4:Lombok @Builder注解
@Builder
public class User {
private String name;
private Integer age;
private String email;
}
// 使用:User user = User.builder().name("张三").age(25).build();
2. 适用场景总结
| 复杂对象创建 | 电脑、汽车、房屋等包含多个组件的对象 |
| 多种组合配置 | 同一类产品有不同的配置组合 |
| 逐步构建 | 需要分步骤创建的对象 |
| 不可变对象 | 需要保证线程安全的不可变对象 |
| 参数众多 | 包含很多可选参数的类 |
六、与工厂模式的区别
对比表格
| 设计目的 | 分步构建复杂对象 | 批量创建同类对象 |
| 关注点 | 对象的构建过程 | 对象的创建 |
| 复杂度 | 适用于复杂对象 | 适用于简单对象 |
| 参数设置 | 支持链式调用,灵活设置 | 通过构造函数或方法参数一次性设置 |
| 构建方式 | 逐步构建,可以控制构建步骤 | 一步到位创建对象 |
| 产品类型 | 可以创建不同类型的产品 | 通常创建同一类型的产品 |
| 代码示例 | User.builder().name("张三").age(25).build() | UserFactory.createUser("张三", 25) |
核心区别
// 工厂模式:关注创建,一步到位
interface UserFactory {
User createUser(String name, Integer age);
}
class DefaultUserFactory implements UserFactory {
@Override
public User createUser(String name, Integer age) {
return new User(name, age);
}
}
// 使用:User user = factory.createUser("张三", 25);
// 建造者模式:关注构建过程,逐步设置
class User {
private String name;
private Integer age;
private String email;
private User(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.email = builder.email;
}
public static class Builder {
private String name;
private Integer age;
private String email;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder age(Integer age) {
this.age = age;
return this;
}
public Builder email(String email) {
this.email = email;
return this;
}
public User build() {
return new User(this);
}
}
}
// 使用:User user = new User.Builder().name("张三").age(25).email("test@example.com").build();
七、最佳实践
1. 使用建议
/**
* 建造者模式最佳实践示例
*/
public class BestPracticeBuilder {
// ✅ 推荐:使用静态内部类Builder
public class GoodExample {
private final String name;
private final Integer age;
private GoodExample(Builder builder) {
this.name = builder.name;
this.age = builder.age;
}
public static class Builder {
private String name;
private Integer age;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder age(Integer age) {
this.age = age;
return this;
}
public GoodExample build() {
return new GoodExample(this);
}
}
}
// ✅ 推荐:在build()方法中进行参数校验
public class GoodExampleWithValidation {
private final String name;
private final Integer age;
private GoodExampleWithValidation(Builder builder) {
this.name = builder.name;
this.age = builder.age;
}
public static class Builder {
private String name;
private Integer age;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder age(Integer age) {
this.age = age;
return this;
}
public GoodExampleWithValidation build() {
// 参数校验
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("name cannot be empty");
}
if (age == null || age < 0) {
throw new IllegalArgumentException("age must be positive");
}
return new GoodExampleWithValidation(this);
}
}
}
}
2. 注意事项
| 参数校验 | 在build()方法中进行参数校验,而不是在setter方法中 |
| 不可变性 | 使用final字段和私有构造方法保证对象不可变 |
| 默认值 | 为可选参数设置合理的默认值 |
| 返回类型 | Builder的setter方法返回this,支持链式调用 |
| 线程安全 | 建造者创建的对象通常是线程安全的 |
| 合理使用 | 不要为所有类都创建Builder,仅适用于复杂对象 |
3. 使用Lombok简化代码
// 使用Lombok @Builder注解自动生成Builder类
import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class User {
private final String name;
private final Integer age;
@Builder.Default
private String email = "default@example.com";
@Builder.Default
private Boolean active = true;
}
// 使用方式
public class Main {
public static void main(String[] args) {
User user = User.builder()
.name("张三")
.age(25)
.email("zhangsan@example.com")
.build();
System.out.println(user);
// 输出:User(name=张三, age=25, email=zhangsan@example.com, active=true)
}
}
4. Spring中的建造者模式应用
// Spring UriComponentsBuilder – URL构建
import org.springframework.web.util.UriComponentsBuilder;
String uri = UriComponentsBuilder.fromHttpUrl("https://api.example.com/users")
.queryParam("page", 1)
.queryParam("size", 10)
.queryParam("sort", "id,desc")
.build()
.toUriString();
// Spring ResponseEntity构建
import org.springframework.http.ResponseEntity;
ResponseEntity<String> response = ResponseEntity.ok()
.header("Custom-Header", "value")
.body("Success");
八、总结
建造者模式是一种非常实用的创建型设计模式,它通过将复杂对象的构建与表示分离,使得代码更加清晰、灵活、易于维护。
核心要点回顾
选择建议
- 需要复杂对象构建 → 使用建造者模式
- 参数众多且可选 → 使用建造者模式
- 需要不可变对象 → 使用建造者模式
- 简单对象创建 → 使用工厂模式或构造函数
- 大量同类对象创建 → 使用工厂模式


