一、前言

今天继续介绍 Java 设计模式中的创建型模式--建造者模式。上篇设计模式的主题为 《Java 设计模式之抽象工厂模式(三)》

二、简单介绍

建造者模式/生成器模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。

建造者模式实现过程通常分成 2 个步骤:构建(Builder)和装配(Director)。 此处的英文不是对汉字的翻译而是为了说明这两个步骤需要用到的接口类型。

2.1 应用场景

  1. 对象的创建:建造者模式是为对象的创建而设计的模式。如:StringBuilder、DomBuilder、SAXBuilder。

  2. 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象。

  3. 关注对象创建的各部分的创建过程:不同的工厂(Builder)对产品属性有不同的创建方法。

三、实现方式

同样地,我们还是以创建轿车为例。

实体类:

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
public class Car {

private Engine engine;

private Tyre tyre;

private Seat seat;

public void intro() {
this.engine.intro();
this.tyre.intro();
this.seat.intro();
}

public Engine getEngine() {
return engine;
}

public void setEngine(Engine engine) {
this.engine = engine;
}

public Tyre getTyre() {
return tyre;
}

public void setTyre(Tyre tyre) {
this.tyre = tyre;
}

public Seat getSeat() {
return seat;
}

public void setSeat(Seat seat) {
this.seat = seat;
}

}

class Engine {

public void intro() {
System.out.println("开得快");
}
}

class Tyre {
public void intro() {
System.out.println("耐磨防滑");
}
}

class Seat {
public void intro() {
System.out.println("坐得舒适");
}
}

Car 类的实例就是一个复合对象。

未使用建造者模式时,客户端调用如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Client {

public static void main(String[] args) {
// 创建组装部件
Engine engine = new Engine();
Tyre tyre = new Tyre();
Seat seat = new Seat();
// 组装
Car car = new Car();
car.setEngine(engine);
car.setTyre(tyre);
car.setSeat(seat);

car.intro();

}
}

上边的代码中,违背了单一职责原则,客户端与多个类进行了耦合,导致代码扩展性不强。

接下来我们使用建造者模式让代码变得灵活起来。

Builder 接口与实现类,用来实现构建过程:

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
public interface CarBuilder {

Engine buildEngine();

Tyre buildTyre();

Seat buildSeat();
}

class MyCarBuilder implements CarBuilder {

@Override
public Engine buildEngine() {
return new Engine();
}

@Override
public Tyre buildTyre() {
return new Tyre();
}

@Override
public Seat buildSeat() {
return new Seat();
}

}

此处使用了工厂模式创建组装轿车的各个部件。很多时候,设计模式并不是单独使用,而是配合使用。

为了编写和测试方便,笔者没有对 Engine、Tyre 和 Seat 类进行抽象。

Director 接口与实现类,用来实现装配过程:

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
public interface CarDirector {

Car directCar();
}

class MyCarDirector implements CarDirector {

private CarBuilder carBuilder;

public MyCarDirector(CarBuilder carBuilder) {
this.carBuilder = carBuilder;
}



@Override
public Car directCar() {
Engine engine = this.carBuilder.buildEngine();
Tyre tyre = this.carBuilder.buildTyre();
Seat seat = this.carBuilder.buildSeat();
// 装配
Car car = new Car();
car.setEngine(engine);
car.setTyre(tyre);
car.setSeat(seat);

return car;
}

}

通过 directCar 方法,隐藏复合对象(Car 实例)的创建过程。

客户端:

1
2
3
4
5
6
7
8
9
10
11
12
public class Client {

public static void main(String[] args) {

CarDirector director = new MyCarDirector(new MyCarBuilder());

Car car = director.directCar();

car.intro();

}
}

现在,客户端代码变得简洁了。因为建造者模式遵循了依赖倒转原则,我们只要将客户端的 Builder 或 Director 替换不同的接口实现类(多态),就能体现出代码灵活性了。

UML 类图表示如下: