建造者模式概述
建造者模式可以将部件本身和它们的组装过程分开,关注如何一步一步地创建一个包含多个组成部分的复杂对象。用户只需要指定对象的类型即可得到该对象,而无需知道其内部的具体构造细节。
定义: 建造者模式:讲一个复杂对象的构建于它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式是一种对象创建型模式,它将客户端与包含多个部件的复杂对象的创建过程分离,客户端无需知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可。
建造者模式的结构与实现
建造者模式的结构

建造者模式包含以下四个角色:
Builder(抽象建造者):它为创建一个产品对象各个部件指定抽象接口,在该接口中一般声明两类方法。一类方法是buildPartX(),他们用来创建复杂对象的各个部件;另一类方法是getResult(),他们用于返回复杂对象。Builder既可以是抽象类,也可以是接口。
ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确所创建的复杂对象,还可以提供一个方法返回创建好的复杂产品对象。
Product(产品):它是构被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。
Director(指挥者):指挥者又被称为导员类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在着关联关系 ,可以在其consttruct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。客户端一般只需要与指挥者进行交互,在客户端确定具体建造者的类型,并实例化具体建造者对象,然后通过指挥者类的构造函数或者Setter方法将对象传入指挥者类中。
建造者模式的实现
以构建电脑为例,展示建造者模式的具体实现(使用Java伪代码):
1. 产品类:Computer
包含多个部件,代表最终被构建的对象。
class Computer {
private String cpu; // CPU部件
private String memory; // 内存部件
private String disk; // 硬盘部件
// 部件的setter方法
public void setCpu(String cpu) { this.cpu = cpu; }
public void setMemory(String memory) { this.memory = memory; }
public void setDisk(String disk) { this.disk = disk; }
// 显示产品信息
public void showInfo() {
System.out.println("电脑配置:CPU=" + cpu + ", 内存=" + memory + ", 硬盘=" + disk);
}
}
2. 抽象建造者:IComputerBuilder
定义构建电脑的抽象步骤。
interface IComputerBuilder {
void buildCpu(); // 构建CPU
void buildMemory(); // 构建内存
void buildDisk(); // 构建硬盘
Computer getComputer(); // 返回最终产品
}
3. 具体建造者:LenovoBuilder & DellBuilder
实现抽象接口,完成具体品牌电脑的部件构建。
// 联想电脑建造者
class LenovoBuilder implements IComputerBuilder {
private Computer computer = new Computer();
@Override
public void buildCpu() { computer.setCpu("Intel i7-13700K"); }
@Override
public void buildMemory() { computer.setMemory("16GB DDR5"); }
@Override
public void buildDisk() { computer.setDisk("1TB SSD"); }
@Override
public Computer getComputer() { return computer; }
}
// 戴尔电脑建造者
class DellBuilder implements IComputerBuilder {
private Computer computer = new Computer();
@Override
public void buildCpu() { computer.setCpu("AMD Ryzen 7 7800X3D"); }
@Override
public void buildMemory() { computer.setMemory("32GB DDR5"); }
@Override
public void buildDisk() { computer.setDisk("2TB SSD"); }
@Override
public Computer getComputer() { return computer; }
}
4. 指挥者:Director
控制构建流程,按顺序调用建造者的方法。
class Director {
// 接收抽象建造者,构建产品
public Computer construct(IComputerBuilder builder) {
builder.buildCpu(); // 第一步:装CPU
builder.buildMemory(); // 第二步:装内存
builder.buildDisk(); // 第三步:装硬盘
return builder.getComputer(); // 返回成品
}
}
5. 客户端调用
通过指挥者和具体建造者获取不同产品。
public class Client {
public static void main(String[] args) {
Director director = new Director();
// 构建联想电脑
IComputerBuilder lenovoBuilder = new LenovoBuilder();
Computer lenovoPc = director.construct(lenovoBuilder);
lenovoPc.showInfo(); // 输出:电脑配置:CPU=Intel i7-13700K, 内存=16GB DDR5, 硬盘=1TB SSD
// 构建戴尔电脑
IComputerBuilder dellBuilder = new DellBuilder();
Computer dellPc = director.construct(dellBuilder);
dellPc.showInfo(); // 输出:电脑配置:CPU=AMD Ryzen7 7800X3D, 内存=32GB DDR5, 硬盘=2TB SSD
}
}
指挥者类Director有两个作用:一方面它隔离了客户端与创建过程;另一方面它控制了产品对象的创建过程,包括某个builderPartX()方法是否被调用以及多个builderPartX()方法调用的先后次序等。
指挥者类的深入讨论
省略director
客户端直接控制步骤
// Product类
class Computer {
private String cpu;
private String memory;
private String disk;
public void setCpu(String cpu) { this.cpu = cpu; }
public void setMemory(String memory) { this.memory = memory; }
public void setDisk(String disk) { this.disk = disk; }
public void showInfo() {
System.out.println("CPU: " + cpu + ", Memory: " + memory + ", Disk: " + disk);
}
}
// 抽象Builder
interface IComputerBuilder {
void buildCpu();
void buildMemory();
void buildDisk();
Computer getComputer();
}
// 具体Builder(联想电脑)
class LenovoBuilder implements IComputerBuilder {
private Computer computer = new Computer();
@Override public void buildCpu() { computer.setCpu("Intel i7-13700K"); }
@Override public void buildMemory() { computer.setMemory("16GB DDR5"); }
@Override public void buildDisk() { computer.setDisk("1TB SSD"); }
@Override public Computer getComputer() { return computer; }
}
// 客户端调用(手动控制步骤)
public class Client {
public static void main(String[] args) {
IComputerBuilder builder = new LenovoBuilder();
// 客户端按顺序调用部件构建方法
builder.buildCpu();
builder.buildMemory();
builder.buildDisk();
Computer lenovoPc = builder.getComputer();
lenovoPc.showInfo();
}
}
Builder内部封装流程
在抽象Builder中增加 build()方法,封装默认步骤:
// 抽象Builder(新增build()方法)
interface IComputerBuilder {
void buildCpu();
void buildMemory();
void buildDisk();
Computer getComputer();
// 内部封装流程
default IComputerBuilder build() {
buildCpu();
buildMemory();
buildDisk();
return this;
}
}
// 客户端调用(无需手动控制步骤)
public class Client {
public static void main(String[] args) {
Computer lenovoPc = new LenovoBuilder()
.build() // 调用内部封装的流程
.getComputer();
lenovoPc.showInfo();
}
}
引入钩子方法的建造者模式
钩子方法是抽象Builder中定义的布尔型方法,用于动态决定是否执行某个构建步骤,支持可选部件的构建,让流程更灵活。
1. 核心逻辑
- 钩子方法:返回
boolean值,由具体Builder实现(如isNeedGpu())。 - 流程调整:
Director在构建时根据钩子结果,决定是否执行某个部件的构建步骤(如是否添加独立显卡)。
2. 代码示例
步骤1:扩展Product类(新增可选部件)
class Computer {
private String cpu;
private String memory;
private String disk;
private String gpu; // 可选部件(独立显卡)
public void setCpu(String cpu) { this.cpu = cpu; }
public void setMemory(String memory) { this.memory = memory; }
public void setDisk(String disk) { this.disk = disk; }
public void setGpu(String gpu) { this.gpu = gpu; }
public void showInfo() {
String info = "CPU: " + cpu + ", Memory: " + memory + ", Disk: " + disk;
if (gpu != null) info += ", GPU: " + gpu;
System.out.println(info);
}
}
抽象Builder(增加钩子和可选部件方法)
interface IComputerBuilder {
void buildCpu();
void buildMemory();
void buildDisk();
void buildGpu(); // 可选部件构建方法
boolean isNeedGpu(); // 钩子方法:是否需要GPU
Computer getComputer();
}
具体Builder(实现钩子方法)
// 联想电脑(需要GPU)
class LenovoBuilder implements IComputerBuilder {
private Computer computer = new Computer();
@Override public void buildCpu() { computer.setCpu("Intel i7-13700K"); }
@Override public void buildMemory() { computer.setMemory("16GB DDR5"); }
@Override public void buildDisk() { computer.setDisk("1TB SSD"); }
@Override public void buildGpu() { computer.setGpu("NVIDIA RTX 4070"); }
@Override public boolean isNeedGpu() { return true; } // 钩子返回true
@Override public Computer getComputer() { return computer; }
}
// 戴尔电脑(不需要GPU)
class DellBuilder implements IComputerBuilder {
private Computer computer = new Computer();
@Override public void buildCpu() { computer.setCpu("AMD Ryzen 7 7800X3D"); }
@Override public void buildMemory() { computer.setMemory("32GB DDR5"); }
@Override public void buildDisk() { computer.setDisk("2TB SSD"); }
@Override public void buildGpu() {} // 空实现(无需GPU)
@Override public boolean isNeedGpu() { return false; } // 钩子返回false
@Override public Computer getComputer() { return computer; }
}
Director(结合钩子调整流程)
class Director {
public Computer construct(IComputerBuilder builder) {
builder.buildCpu();
builder.buildMemory();
builder.buildDisk();
// 根据钩子判断是否构建GPU
if (builder.isNeedGpu()) {
builder.buildGpu();
}
return builder.getComputer();
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
Director director = new Director();
Computer lenovoPc = director.construct(new LenovoBuilder());
Computer dellPc = director.construct(new DellBuilder());
lenovoPc.showInfo(); // 包含GPU
dellPc.showInfo(); // 无GPU
}
}
建造者模式优缺点与适用环境
建造者模式的优点
- 封装性优异
分离对象的“构建逻辑”与“表示形式”,用户无需了解产品内部的组装细节,只需通过指挥者即可获取成品。
示例:用户购买定制电脑时,无需知道CPU如何安装、内存如何插卡,只需告诉商家配置需求(指挥者),商家(具体建造者)按流程组装即可。 - 精细控制构建过程
允许分步、有序地构建产品,每个步骤均可定制化调整。
示例:制作蛋糕时,可先选择蛋糕胚类型(戚风/海绵),再决定奶油口味(草莓/巧克力),最后添加装饰(水果/糖霜),每个步骤都能灵活修改。 - 扩展性强
新增产品类型时,只需添加对应的具体建造者类,无需修改现有代码(符合开闭原则)。
示例:汽车工厂原本生产轿车,若要新增SUV产品线,只需新增“SUV建造者”类,指挥者的构建流程(底盘→发动机→车身→内饰)保持不变。 - 复用性高
相同的构建流程可复用在不同产品上,减少重复代码。
示例:手机制造中,旗舰机和中端机的组装流程(主板→屏幕→电池→摄像头)一致,但部件规格不同,可复用同一指挥者逻辑。
建造者模式的缺点
- 产品差异过大时不适用
若产品之间的核心部件或构建步骤差异显著,抽象建造者难以定义通用的构建接口,导致模式失效。
示例:用建造者模式同时生产汽车和飞机,两者的部件(发动机类型、底盘结构)完全不同,无法通过统一的抽象建造者描述。 - 系统复杂度提升
引入抽象建造者、具体建造者、指挥者等多个角色,增加了类的数量,使系统结构更复杂。
示例:简单产品(如一杯咖啡)无需拆分多个步骤,使用建造者模式会显得“小题大做”,不如直接用工厂模式高效。 - 维护成本较高
若产品内部结构发生变化(如新增部件),需修改所有具体建造者的相关方法,增加维护工作量。
示例:手机新增无线充电模块后,所有手机建造者(旗舰机、中端机)都需添加“安装无线充电模块”的步骤。
建造者模式的适用环境
| 适用场景 | 详细说明 |
|---|---|
| 产品内部结构复杂 | 产品包含多个相互依赖的部件,需按特定顺序组装(如汽车、电脑)。 |
| 需生成不同表示的同类型产品 | 构建流程相同,但部件规格或组合方式不同(如不同配置的电脑、不同型号的手机)。 |
| 严格控制构建流程 | 要求产品必须按固定顺序生成,或需记录构建过程中的中间状态(如定制家具的分步制作)。 |
| 隔离创建与使用 | 希望隐藏产品的创建细节,避免用户直接操作内部部件(如软件框架中的复杂对象生成)。 |
Comments