建造者模式(Builder Pattern)是一种创建型设计模式,它将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。这种模式允许你分步骤构建一个复杂对象,并且可以在构建过程中进行不同的配置。
模式的核心组件
建造者模式通常包含以下四个核心组件:
- 产品(Product):要构建的复杂对象。
- 抽象建造者(Builder):定义了构建产品各个部分的抽象接口。
- 具体建造者(Concrete Builder):实现抽象建造者接口,完成产品各部分的具体构建。
- 指挥者(Director):负责安排复杂对象的构建顺序,并使用建造者对象构建产品。
简单实现
让我们通过一个示例来详细说明建造者模式的实现。假设我们要构建一个电脑(Computer)对象,它包含 CPU、内存、硬盘和显卡等组件。
首先,定义产品类:
// 产品类:电脑
public class Computer {
private String cpu;
private String memory;
private String hardDisk;
private String graphicsCard;
// 私有构造函数,只能通过Builder创建Computer
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.memory = builder.memory;
this.hardDisk = builder.hardDisk;
this.graphicsCard = builder.graphicsCard;
}
// Getter方法
public String getCpu() {
return cpu;
}
public String getMemory() {
return memory;
}
public String getHardDisk() {
return hardDisk;
}
public String getGraphicsCard() {
return graphicsCard;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", hardDisk='" + hardDisk + '\'' +
", graphicsCard='" + graphicsCard + '\'' +
'}';
}
// 静态内部类:Builder
public static class Builder {
private String cpu;
private String memory;
private String hardDisk;
private String graphicsCard;
// 设置CPU,返回Builder实例以便链式调用
public Builder setCpu(String cpu) {
this.cpu = cpu;
return this;
}
// 设置内存,返回Builder实例以便链式调用
public Builder setMemory(String memory) {
this.memory = memory;
return this;
}
// 设置硬盘,返回Builder实例以便链式调用
public Builder setHardDisk(String hardDisk) {
this.hardDisk = hardDisk;
return this;
}
// 设置显卡,返回Builder实例以便链式调用
public Builder setGraphicsCard(String graphicsCard) {
this.graphicsCard = graphicsCard;
return this;
}
// 构建Computer对象
public Computer build() {
// 可以在这里添加参数验证逻辑
if (cpu == null || memory == null || hardDisk == null) {
throw new IllegalArgumentException("CPU、内存和硬盘是必需的");
}
return new Computer(this);
}
}
}
然后,使用建造者模式创建电脑对象:
public class BuilderPatternExample {
public static void main(String[] args) {
// 使用Builder创建电脑对象
Computer gamingComputer = new Computer.Builder()
.setCpu("Intel i9-12900K")
.setMemory("32GB DDR5")
.setHardDisk("2TB NVMe SSD")
.setGraphicsCard("NVIDIA RTX 3080")
.build();
Computer officeComputer = new Computer.Builder()
.setCpu("Intel i5-12400")
.setMemory("16GB DDR4")
.setHardDisk("512GB SSD")
.build(); // 办公电脑可以不设置独立显卡
System.out.println("游戏电脑配置:" + gamingComputer);
System.out.println("办公电脑配置:" + officeComputer);
}
}
如上是一个建造者模式的简单实现,是不是感觉超级简单,下面是经典的实现方式
经典实现
// 1. 产品类:电脑
public class Computer {
private String cpu;
private String memory;
private String hardDisk;
private String graphicsCard;
// 构造函数和Getter方法
public Computer(String cpu, String memory, String hardDisk, String graphicsCard) {
this.cpu = cpu;
this.memory = memory;
this.hardDisk = hardDisk;
this.graphicsCard = graphicsCard;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", hardDisk='" + hardDisk + '\'' +
", graphicsCard='" + graphicsCard + '\'' +
'}';
}
}
// 2. 抽象建造者接口
public interface ComputerBuilder {
void buildCPU();
void buildMemory();
void buildHardDisk();
void buildGraphicsCard();
Computer getComputer();
}
// 3. 具体建造者:游戏电脑建造者
public class GamingComputerBuilder implements ComputerBuilder {
private Computer computer;
public GamingComputerBuilder() {
this.computer = new Computer(null, null, null, null);
}
@Override
public void buildCPU() {
computer.setCpu("Intel i9-12900K");
}
@Override
public void buildMemory() {
computer.setMemory("32GB DDR5");
}
@Override
public void buildHardDisk() {
computer.setHardDisk("2TB NVMe SSD");
}
@Override
public void buildGraphicsCard() {
computer.setGraphicsCard("NVIDIA RTX 3080");
}
@Override
public Computer getComputer() {
return computer;
}
}
// 3. 具体建造者:办公电脑建造者
public class OfficeComputerBuilder implements ComputerBuilder {
private Computer computer;
public OfficeComputerBuilder() {
this.computer = new Computer(null, null, null, null);
}
@Override
public void buildCPU() {
computer.setCpu("Intel i5-12400");
}
@Override
public void buildMemory() {
computer.setMemory("16GB DDR4");
}
@Override
public void buildHardDisk() {
computer.setHardDisk("512GB SSD");
}
@Override
public void buildGraphicsCard() {
// 办公电脑可以不设置独立显卡
}
@Override
public Computer getComputer() {
return computer;
}
}
// 4. 指挥者:控制构建过程
public class ComputerDirector {
private ComputerBuilder builder;
public ComputerDirector(ComputerBuilder builder) {
this.builder = builder;
}
public void constructComputer() {
builder.buildCPU();
builder.buildMemory();
builder.buildHardDisk();
builder.buildGraphicsCard();
}
public Computer getComputer() {
return builder.getComputer();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 构建游戏电脑
ComputerBuilder gamingBuilder = new GamingComputerBuilder();
ComputerDirector director = new ComputerDirector(gamingBuilder);
director.constructComputer();
Computer gamingComputer = director.getComputer();
// 构建办公电脑
ComputerBuilder officeBuilder = new OfficeComputerBuilder();
director = new ComputerDirector(officeBuilder);
director.constructComputer();
Computer officeComputer = director.getComputer();
System.out.println("游戏电脑配置:" + gamingComputer);
System.out.println("办公电脑配置:" + officeComputer);
}
}
模式的优点
- 分离构建和表示:使得构建算法可以独立于产品的表示,提高了系统的可扩展性。
- 分步构建:可以分步骤构建一个复杂对象,允许在构建过程中进行不同的配置。
- 链式调用:通过链式调用方法设置属性,使代码更简洁易读。
- 参数验证:可以在
build()
方法中添加参数验证逻辑,确保对象的完整性。
模式的应用场景
- 复杂对象构建:当创建一个对象需要很多步骤,并且这些步骤的顺序可能不同。
- 可选参数较多:当一个类的构造函数有很多参数,特别是其中很多是可选参数时。
- 构建不同表示:当需要创建同一个产品的不同表示时。
与其他模式的比较
- 工厂模式:工厂模式关注的是整体对象的创建,而建造者模式关注的是对象的分步构建。
- 抽象工厂模式:抽象工厂模式返回的是一系列相关产品,而建造者模式返回的是一个完整的产品。
建造者模式在实际开发中非常常用,特别是在创建复杂对象时。它能够使代码更加清晰、灵活,并且易于维护。另外Lombok 的@Builder
注解是一个强大的工具,它能自动生成流式 API 风格的 "建造者模式 (Builder Pattern)" 代码,从而避免编写大量样板代码。使用该注解可以让代码更简洁,同时保持建造者模式的优势。