创建型设计模式的一种

【DP】定义

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

使用场景

需要构建一批构建过程相同但表示不同的产品,而构建过程非常复杂,为了防止构建过程遗漏步骤,需要建造者模式

类图

建造者模式

举例

假设有一套单据,结构相同,但是很复杂,每个单据的显示内容各不相同。类结构如下:

1
2
3
4
5
6
7
8
9
10
11
/**
* 单据类,省略getter、setter方法
*/
public class Invoice {
private LeftHeader leftHeader;
private RightHeader rightHeader;
private LeftBody leftBody;
private RightBody rightBody;
private LeftTail leftTail;
private RightTail rightTail;
}

那么为了构建这样一个类,需要调用各个部分的构造方法,因为重复代码太多,很容易在写的过程中遗漏某个部分,因此可以使用建造者模式构建一个Builder接口,将所有的方法封装起来。代码如下:

1
2
3
4
5
6
public interface Builder {
LeftHeader buildLeftHeader();
RightHeader buildRightHeader();
// 省略其他方法......
Invoice buildInvoice();
}

在创建不同的单据时,可以创建具体的建造者类,比如:

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
/**
* 账单单据
*/
public class BillBuilder implements Builder{
private Invoice billInvoice;
public BillBuilder() {
billInvoice = new Invoice();
}
@Override
public LeftHeader buildLeftHeader() {
LeftHeader leftHeader = new LeftHeader();
// do something with leftHeader
billInvoice.setLeftHeader(leftHeader);
}
@Override
public RightHeader buildRightHeader() {
RightHeader rightHeader = new RightHeader();
// do something with rightHeader
billInvoice.setRightHeader(rightHeader);
}
@Override
public Invoice buildInvoice() {
return billInvoice;
}
}

有了接口的约束,就不会少构建Invoice的某个部分了。但是在客户端调用时,仍然会有可能少调用实现的方法,那么就需要建造者模式的核心类Director(指挥者)了,代码如下:

1
2
3
4
5
6
7
8
public class Director {
public Invoice buildInvoice(Builder builder) {
builder.buildLeftHeader();
builder.buildRightHeader();
// 省略其他方法......
return builder.buildInvoice();
}
}

客户端调用Director就可以透明的创建一个对象,而不用担心会少调用某个方法了,客户端代码如下:

1
2
3
4
5
6
7
public class Main {
public static void main() {
Builder billBuilder = new BillBuilder();
Director director = new Director();
Invoice billInvoice = director.buildInvoice(billBuilder);
}
}

注意事项

  1. 建造者模式主要用于一些复杂对象但是结构相似的对象的构建,上文中的例子只写了billInvoice,当然也可以有stockInvoice等等
  2. 建造者模式在只有一个具体的构建对象(比如只有一个billInvoice)时,可以将建造者的具体实现类和Director指挥者类合并在一起,将Director中的build方法放到建造者具体实现类的build方法中
  3. 抽象工厂模式类似,都能够约束创建对象的过程,让客户端能够透明的创建对象,但是二者的目的和实现方式不同:抽象工厂模式是为了抽象实现接口而定义了抽象工厂类,建造者模式是为了复用复杂对象的构建过程,保证客户端不会遗漏对象的某个部分,从而创建了指挥者类。