建造者模式將一個複雜對象的構建與其表示分離,使得相同的構建過程可以創建不同的表示。屬於創建型模式,核心解決「參數過多、構建邏輯複雜、不可變對象構建」等問題。
public final class User {
private final String userId; // 必填
private final String username; // 必填
private final String email; // 可選
private final String phone; // 可選
private final String address; // 可選
private final int age; // 可選
private final boolean vip; // 可選
private User(Builder builder) {
this.userId = builder.userId;
this.username = builder.username;
this.email = builder.email;
this.phone = builder.phone;
this.address = builder.address;
this.age = builder.age;
this.vip = builder.vip;
}
public static class Builder {
// 必填參數
private final String userId;
private final String username;
// 可選參數(默認值)
private String email = "";
private String phone = "";
private String address = "";
private int age = 0;
private boolean vip = false;
public Builder(String userId, String username) {
this.userId = userId;
this.username = username;
}
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 age(int age) {
this.age = age;
return this;
}
public Builder vip(boolean vip) {
this.vip = vip;
return this;
}
public User build() {
// 參數校驗
if (userId == null || username == null) {
throw new IllegalStateException("必填字段不能為空");
}
return new User(this);
}
}
// Getter 方法...
@Override
public String toString() {
return "User{userId='" + userId + "', username='" + username + "', email='" + email + "'...}";
}
}
// 鏈式調用,語義清晰
User user = new User.Builder("1001", "zhangsan")
.email("zhangsan@example.com")
.phone("13800138000")
.age(28)
.vip(true)
.build();
System.out.println(user);
// User{userId='1001', username='zhangsan', email='zhangsan@example.com'...}
// 指揮者:封裝固定構建流程
public class UserDirector {
public User constructStandardUser(User.Builder builder) {
return builder.email("default@company.com").vip(false).build();
}
public User constructVipUser(User.Builder builder) {
return builder.email("vip@company.com").vip(true).age(30).build();
}
}
// 使用
UserDirector director = new UserDirector();
User standard = director.constructStandardUser(new User.Builder("1002", "lisi"));
User vip = director.constructVipUser(new User.Builder("1003", "wangwu"));
| 場景 | 說明 |
|---|---|
| HTTP 請求構建 | OkHttp Request.Builder、HttpClient Request.Builder |
| 數據庫連接配置 | HikariConfig、Druid DataSource 建造者 |
| 文檔生成 | PDF/Word/Excel 文檔構建器 |
| 複雜查詢條件 | JPA CriteriaBuilder、MyBatis Example.Builder |
| 對象轉換/DTO 組裝 | 避免 Setter 滥用,保證不可變性 |
@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class User {
@NonNull private final String userId;
@NonNull private final String username;
private final String email;
private final String phone;
// ...
}
Lombok 自動生成 Builder 類、鏈式 Setter、build() 方法、私有構造器,極大減少樣板代碼。
| 維度 | 工廠模式 | 建造者模式 |
|---|---|---|
| 適用對象 | 較簡單、構建邏輯固定 | 複雜、多可選參數、構建步驟可變 |
| 構建控制 | 一次性創建 | 分步構建、可中途校驗 |
| 不可變性 | 需手動保證 | 天然支持(final 字段+私有構造器) |
建造者模式是構建複雜不可變對象的最佳實踐之一,廣泛應用於主流框架與庫中。掌握其核心結構、變體與工具化簡化(Lombok),能顯著提升代碼質量與可維護性。實戰中根據對象複雜度權衡使用,避免過度設計。