建造者模式 (Builder Pattern)
什么是建造者模式?
建造者模式是一种创建型设计模式,它允许你分步骤创建复杂对象。该模式能让你使用相同的创建过程生成不同类型和形式的对象。
简单来说:建造者模式就是将复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
生活中的例子
想象一家快餐店:
- 汉堡:可以有或没有芝士、番茄、生菜、洋葱等
- 点餐过程 :
- 选择面包
- 选择肉饼
- 选择配料(芝士、番茄、生菜、洋葱等)
- 选择酱料
建造者模式可以让你:
- 灵活地选择不同的配料组合
- 创建不同类型的汉堡(芝士汉堡、蔬菜汉堡、双层汉堡等)
- 使用相同的构建过程
为什么需要建造者模式?
传统方式的问题
java
// 使用构造函数创建对象
Computer computer = new Computer("Intel i7", "16GB", "512GB SSD",
"Windows 10", "NVIDIA RTX 3080",
"27英寸显示器", "机械键盘", "无线鼠标");
问题:
- 参数过多:构造函数参数列表过长,难以记忆和使用
- 参数顺序依赖:必须按特定顺序传递参数
- 可选参数处理困难:某些参数可选时,需要多个构造函数
- 可读性差:无法从代码中看出每个参数的含义
建造者模式的优势
java
Computer computer = new Computer.Builder()
.cpu("Intel i7")
.ram("16GB")
.storage("512GB SSD")
.gpu("NVIDIA RTX 3080")
.build();
优势:
- 参数清晰:每个参数都有明确的名称
- 参数顺序无关:可以按任意顺序设置参数
- 可选参数灵活:可选参数可以不设置
- 可读性好:代码清晰易懂
- 不可变对象:可以创建不可变对象
建造者模式的结构
┌─────────────────────┐
│ Product │ 产品
├─────────────────────┤
│ - part1: String │
│ - part2: String │
│ - part3: String │
└─────────────────────┘
┌─────────────────────┐
│ Builder │ 抽象建造者
├─────────────────────┤
│ + build(): Product │
│ + setPart1(): void │
│ + setPart2(): void │
│ + setPart3(): void │
└──────────┬──────────┘
│ 继承
│
┌──────────┴──────────┐
│ ConcreteBuilder │ 具体建造者
├─────────────────────┤
│ - product: Product │
│ + build(): Product │
│ + setPart1(): void │
│ + setPart2(): void │
│ + setPart3(): void │
└─────────────────────┘
┌─────────────────────┐
│ Director │ 指挥者(可选)
├─────────────────────┤
│ - builder: Builder │
│ + construct(): void │
└─────────────────────┘
代码示例
1. 定义产品
java
/**
* 产品:电脑
*/
public class Computer {
private String cpu;
private String ram;
private String storage;
private String gpu;
private String os;
private String monitor;
private String keyboard;
private String mouse;
// 私有构造函数,只能通过Builder创建
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
this.gpu = builder.gpu;
this.os = builder.os;
this.monitor = builder.monitor;
this.keyboard = builder.keyboard;
this.mouse = builder.mouse;
}
/**
* 显示电脑配置
*/
public void display() {
System.out.println("电脑配置:");
System.out.println(" CPU: " + cpu);
System.out.println(" 内存: " + ram);
System.out.println(" 存储: " + storage);
if (gpu != null) System.out.println(" 显卡: " + gpu);
if (os != null) System.out.println(" 操作系统: " + os);
if (monitor != null) System.out.println(" 显示器: " + monitor);
if (keyboard != null) System.out.println(" 键盘: " + keyboard);
if (mouse != null) System.out.println(" 鼠标: " + mouse);
}
/**
* Builder类
*/
public static class Builder {
// 必需参数
private String cpu;
private String ram;
private String storage;
// 可选参数
private String gpu;
private String os;
private String monitor;
private String keyboard;
private String mouse;
public Builder(String cpu, String ram, String storage) {
this.cpu = cpu;
this.ram = ram;
this.storage = storage;
}
public Builder gpu(String gpu) {
this.gpu = gpu;
return this;
}
public Builder os(String os) {
this.os = os;
return this;
}
public Builder monitor(String monitor) {
this.monitor = monitor;
return this;
}
public Builder keyboard(String keyboard) {
this.keyboard = keyboard;
return this;
}
public Builder mouse(String mouse) {
this.mouse = mouse;
return this;
}
public Computer build() {
return new Computer(this);
}
}
}
2. 使用Builder
java
/**
* 建造者模式测试类
* 演示如何使用建造者模式创建不同配置的电脑
*/
public class BuilderTest {
public static void main(String[] args) {
System.out.println("=== 建造者模式测试 ===\n");
// 创建基础配置的办公电脑
System.out.println("--- 办公电脑 ---");
Computer officePC = new Computer.Builder(
"Intel i5",
"8GB",
"256GB SSD"
).os("Windows 10")
.build();
officePC.display();
System.out.println();
// 创建游戏电脑
System.out.println("--- 游戏电脑 ---");
Computer gamingPC = new Computer.Builder(
"Intel i9",
"32GB",
"1TB SSD"
).gpu("NVIDIA RTX 4090")
.os("Windows 11")
.monitor("27英寸 144Hz显示器")
.keyboard("机械键盘")
.mouse("游戏鼠标")
.build();
gamingPC.display();
System.out.println();
// 创建开发电脑
System.out.println("--- 开发电脑 ---");
Computer devPC = new Computer.Builder(
"AMD Ryzen 9",
"64GB",
"2TB NVMe SSD"
).gpu("NVIDIA RTX 3080")
.os("Ubuntu 22.04")
.monitor("双显示器")
.keyboard("HHKB键盘")
.mouse("垂直鼠标")
.build();
devPC.display();
System.out.println("\n=== 建造者模式的优势 ===");
System.out.println("1. 参数清晰:每个参数都有明确的名称");
System.out.println("2. 参数顺序无关:可以按任意顺序设置参数");
System.out.println("3. 可选参数灵活:可选参数可以不设置");
System.out.println("4. 代码可读性好:代码清晰易懂");
System.out.println("5. 不可变对象:可以创建不可变对象");
}
}
建造者模式的优点
- 分步骤创建:可以分步骤创建复杂对象
- 参数清晰:每个参数都有明确的名称
- 代码可读:代码清晰易懂
- 灵活扩展:可以轻松添加新的参数
- 不可变对象:可以创建不可变对象
建造者模式的缺点
- 代码量增加:需要创建Builder类
- 性能开销:创建对象需要额外的步骤
适用场景
- 复杂对象:需要创建复杂对象,且对象有多个组成部分
- 参数众多:构造函数参数过多
- 可选参数:有多个可选参数
- 不同表示:需要使用相同的创建过程创建不同的表示
常见应用场景
- StringBuilder:Java中的StringBuilder
- 文档构建:HTML、XML、JSON文档的构建
- SQL查询构建:动态SQL查询的构建
- 配置对象:配置对象的创建
使用建议
- 参数超过4个:考虑使用建造者模式
- 有可选参数:考虑使用建造者模式
- 需要不可变对象:考虑使用建造者模式
- 简单对象:直接使用构造函数即可
注意事项
⚠️ 建造者模式虽然很好,但不要滥用:
- 如果对象很简单,直接使用构造函数或setter方法
- 如果参数很少(<4个),不需要使用建造者模式
- 建造者模式会增加代码量,要权衡利弊