什么是建造者模式?
建造者模式(Builder Pattern)是一种创建型设计模式,它通过链式调用逐步构建复杂对象。当一个类的构造函数参数过多时,使用建造者模式可以让代码更清晰、更易读。
生活比喻
想象你去电脑城组装电脑。你不需要一次性告诉销售员所有配件(CPU、内存、硬盘、显示器),而是一步一步选择:先选CPU,再选内存,...最后确认配置单。建造者模式就像这个"配置单",让复杂的创建过程变得清晰可控。
为什么需要建造者模式?
传统构造函数的痛苦:参数列表太长
// 如果用传统构造函数,创建对象会变成噩梦
User user = new User("张三", 25, true, "北京", "13800001111",
"zhang@example.com", "XX公司", true, ...);
// 参数太多,谁知道每个参数是什么意思?
// 而且如果有些参数是可选的:
User user = new User("张三", 25, null, null, null, null, null, null, null);
// 这太难看了!
传统Builder实现
public class User {
private String name; // 必填
private int age; // 必填
private String email; // 可选
private String phone; // 可选
private String address; // 可选
private boolean active; // 可选
// 私有构造函数,只能通过Builder创建
private User(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.email = builder.email;
this.phone = builder.phone;
this.address = builder.address;
this.active = builder.active;
}
// 静态内部类Builder
public static class Builder {
// 必填参数
private String name;
private int age;
// 可选参数,使用默认值
private String email = "";
private String phone = "";
private String address = "";
private boolean active = true;
public Builder(String name, int age) {
this.name = name;
this.age = age;
}
// 链式调用方法
public Builder email(String email) {
this.email = email;
return this;
}
public Builder phone(String phone) {
this.phone = phone;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Builder active(boolean active) {
this.active = active;
return this;
}
public User build() {
return new User(this);
}
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age +
", email='" + email + "', phone='" + phone +
"', address='" + address + "', active=" + active + "}";
}
}
Builder模式使用
public class BuilderDemo {
public static void main(String[] args) {
System.out.println("===== 完整参数 =====");
User user1 = new User.Builder("张三", 25)
.email("zhang@example.com")
.phone("13800138000")
.address("北京市朝阳区")
.active(true)
.build();
System.out.println("用户1: " + user1);
System.out.println("\n===== 部分参数 =====");
User user2 = new User.Builder("李四", 30)
.email("li@example.com")
.build();
System.out.println("用户2: " + user2);
System.out.println("\n===== 只有必填参数 =====");
User user3 = new User.Builder("王五", 22)
.build();
System.out.println("用户3: " + user3);
}
}
ComputerBuilder完整示例
再来看一个更复杂的例子——组装电脑配置:
public class Computer {
private String cpu; // 必填
private String ram; // 必填
private String storage; // 可选
private String display; // 可选
private String keyboard; // 可选
private boolean hasWifi; // 可选
private boolean hasBluetooth;
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
this.display = builder.display;
this.keyboard = builder.keyboard;
this.hasWifi = builder.hasWifi;
this.hasBluetooth = builder.hasBluetooth;
}
public static class Builder {
private String cpu;
private String ram;
private String storage = "256GB SSD";
private String display = "14 inch";
private String keyboard = "默认键盘";
private boolean hasWifi = true;
private boolean hasBluetooth = true;
public Builder(String cpu, String ram) {
this.cpu = cpu;
this.ram = ram;
}
public Builder storage(String storage) {
this.storage = storage;
return this;
}
public Builder display(String display) {
this.display = display;
return this;
}
public Builder keyboard(String keyboard) {
this.keyboard = keyboard;
return this;
}
public Builder wifi(boolean hasWifi) {
this.hasWifi = hasWifi;
return this;
}
public Builder bluetooth(boolean hasBluetooth) {
this.hasBluetooth = hasBluetooth;
return this;
}
public Computer build() {
return new Computer(this);
}
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
", storage='" + storage + '\'' +
", display='" + display + '\'' +
", keyboard='" + keyboard + '\'' +
", hasWifi=" + hasWifi +
", hasBluetooth=" + hasBluetooth +
'}';
}
}
// 使用
public class ComputerBuilderDemo {
public static void main(String[] args) {
Computer gaming = new Computer.Builder("Intel i9", "32GB")
.storage("2TB SSD")
.display("27 inch 144Hz")
.keyboard("机械键盘")
.wifi(true)
.bluetooth(true)
.build();
System.out.println("游戏电脑: " + gaming);
Computer office = new Computer.Builder("Intel i5", "16GB")
.build();
System.out.println("办公电脑: " + office);
}
}
建造者模式的优势
代码清晰
链式调用,参数名称明确,无需记住参数顺序
可选参数
可以轻松处理可选参数,不用传null
验证逻辑
可以在build()方法中集中验证
不可变对象
对象在build()时一次性创建完成,保证不可变性
Lombok @Builder(推荐)
如果你使用Lombok,可以自动生成Builder代码:
import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class UserLombok {
private String name;
private int age;
private String email;
private String phone;
}
// Lombok自动生成:
UserLombok user = UserLombok.builder()
.name("张三")
.age(25)
.email("zhang@example.com")
.build();
System.out.println(user);
小结
- 建造者模式通过链式调用逐步构建复杂对象
- 解决构造函数参数过多的问题
- 可以设置必填参数和可选参数
- 提供清晰的代码可读性,参数名称一目了然
- Lombok @Builder注解可以自动生成Builder代码