建造者模式(Builder Pattern)

建造者模式(Builder Pattern)是对象的创建模式。建造者模式可以将一个产品的内部表象(internal representation)与产品的生产过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。

概念

将一个复杂对象的构建与其表象分离,使得同样的构建过程可以创建不同的表示。

  • 适用场景:
    • 构建的对象具有复杂的内部结构。
    • 对象的构建过程需要多个步骤,并且这些步骤可能变化。
    • 希望解耦构建过程与具体实现。

模式结构

建造者模式通常包含以下角色:

  • Product: 要构建的复杂对象
  • Builder: 定义构建产品的各个步骤的接口(如buildPartA(),buildPartB()等),也可以是一个抽象类或接口。
  • ConcreteBuilder: 实现Builder接口,具体完成各部分的构建,并提供一个获取产品的方法。
  • Director: 负责调用构建者中的步骤来构建产品,不关心具体实现,只控制流程。
  • Client: 最终客户端。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class House {  // Product 类
private String foundation;
private String walls;
private String roof;
public void setFoundation(String foundation) {
this.foundation = foundation;
}
public void setWalls(String walls) {
this.walls = walls;
}
public void setRoof(String roof) {
this.roof = roof;
}
public void show() {
System.out.println("Foundation: " + foundation);
System.out.println("Walls: " + walls);
System.out.println("Roof: " + roof);
}
}

interface HouseBuilder { // Builder
void buildFoundation();
void buildWalls();
void buildRoof();
House getHouse();
}

class ConcreteHouseBuilder implements HouseBuilder { // ConcreteBuilder
private House house = new House();
public void buildFoundation() {
house.setFoundation("Built with bricks");
}
public void buildWalls() {
house.setWalls("Reinforced concrete walls");
}
public void buildRoof() {
house.setRoof("Tile roof");
}
public House getHouse() {
return house;
}
}

class HouseDirector { // Director
private HouseBuilder builder;
public HouseDirector(HouseBuilder builder) {
this.builder = builder;
}
public void constructHouse() {
builder.buildFoundation();
builder.buildWalls();
builder.buildRoof();
}
}

public class Client { // Client
public static void main(String[] args) {
// 创建建造者
HouseBuilder builder = new ConcreteHouseBuilder();
// 创建指挥者并传入建造者
HouseDirector director = new HouseDirector(builder);
// 指挥者开始构建
director.constructHouse();
// 获取最终产品
House house = builder.getHouse();
house.show();
}
}

优点: 分离构建逻辑和表示;多样化输出;控制构建过程
缺点: 不适合简单对象,如果对象构造过程简单,使用该模式反而增加复杂度;需要定义多个类,增加了系统的类数量,增加了理解成本。

场景举例

  • 构建不同配置的计算机(cpu、内存、硬盘等)
  • 生成不同风格的文档(PDF、HTML、Word)
  • 组装汽车的不同型号(发动机、轮子、颜色等)
  • 游戏中的角色的定制(武器、服装、技能等)

和Lombok插件的区别

  1. Lombok的@Builder并不完全等同于GoF的建造者模式。
  2. 它缺少Director角色,也不支持多个ConcreteBuilder实现。
  3. 如需要对构建过程作复杂的控制(如分布构建、条件判断、模板化流程),仍需要手动实现建造者模式。
  4. Lombok的@Builder只对简单对象的私有属性进行构建。