设计模式笔记 - 建造者模式(Builder Pattern)

模式定义

建造者模式(Builder Pattern)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户无需知道内部的具体构建细节。

建造者模式属于对象创建型模式。


模式结构

建造者模式包含如下角色:

  • Builder - 抽象建造者 - 定义了产品的创建方法和返回方法
  • ConcreteBuilder - 具体建造者
  • Director - 指挥者 - 隔离了客户与生产过程,并负责控制产品的生成过程
  • Product - 产品角色

img


模式实例

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
* 本例为McDonald's中超值套餐系列构造。虽然不同的超值套餐都自己不同的特点,但是总体的构造成分都是一致的,主食(汉堡)以及饮料(可乐)等。
*/
// Product - 产品角色
public class ValueMeal {
private Meal meal;
private Drink drink;

public void setMeal(Meal meal) {
this.meal = meal;
}

public void setDrink(Drink drink) {
this.drink = drink;
}

public Meal getMeal(Meal meal) {
return this.meal;
}

public Drink getDrink(Drink drink) {
return this.drink;
}
}

// Builder - 抽象建造者
public interface class valueMealBuilder {
public void buildMeal(Meal meal);
public void buildDrink(Drink drink);
public ValueMeal getValueMeal();
}

// ConcreteBuilder - 具体建造者
// 麦辣鸡腿堡
public class McCrispyPackage implements valueMealBuilder {
private ValueMeal valueMeal = new ValueMeal();

public void buildMeal() {
valueMeal.setMeal(new McCrispyChickenBurger());
}

public void buildDrink() {
valueMeal.setDrink(new CocaCola());
}

public ValueMeal getValueMeal() {
return this.valueMeal;
}
}

// ConcreteBuilder - 具体建造者
// 巨无霸
public class BigMacPackage implements valueMealBuilder {
private ValueMeal valueMeal = new ValueMeal();

public void buildMeal() {
valueMeal.setMeal(new BigMac());
}

public void buildDrink() {
valueMeal.setDrink(new CocaCola());
}

public ValueMeal getValueMeal() {
return this.valueMeal;
}
}

// Direct - 指挥者
public class McDonaldWaiter {
private ValueMealBuilder valueMealBuilder;

public McDonaldWaiter(ValueMealBuilder valueMealBuilder) {
this.valueMealBuilder = valueMealBuilder;
}

public void construct() {
valueMealBuilder.buildMeal();
valueMealBuilder.buildDrink();
}

public ValueMeal getValueMeal() {
valueMealBuilder.getValueMeal();
}

public void setValueMealBuilder(ValueMealBuilder valueMealBuilder) {
this.valueMealBuilder = valueMealBuilder;
}
}

// 测试类
public class Test {
public static void main(String[] args) {
ValueMealBuilder mcCrispyPackage = new McCrispyPackage();
McDonaldWaiter waiter = new McDonaldWaiter(mcCrispyPackage);

waiter.construct();
ValueMeal mcCrispy = waiter.getValueMeal();
}
}

模式分析

  • 建造者模式的重心在于分离构建算法和具体的构造实现,从而使得构建算法可以重用,具体的构造实现可以方便地扩展和切换,从而可以灵活地组合来构造出不同的产品对象。
  • 增加新的具体建造者无需修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性较大,则不适合使用建造者模式,因此其适用范围受到一定的限制。

建造者模式的优点:

  • 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此很方便地替换不同的具体建造者或增加新的具体建造者。
  • 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法当中,使得构建者可以更加专注于逻辑处理部分。

建造者模式的缺点:

  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,增加系统复杂度,难以维护。

模式应用

  • 在游戏软件设计中,不同的地图包括天空、地面和背景等组成部分,不同的人物也包括身体,服装和装备等组成部分,可以利用建造者模式对其设计,通过不同的具体建造者创建不同类型的地图或人物。

与抽象工厂模式的对比:

  • 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,可以类比于汽车组装工厂。而抽象工厂模式返回一系列的相关产品,这些产品位于不同的产品等级结构,构成了一个产品族,可以类比于汽车配件生产工厂
  • 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用具体建造者的相关方法,而是通过指挥者类来指导如何生成对象,它侧重于如何一步步构建一个复杂对象,返回一个完整的对象。


参考资料:

[1] https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/builder.html

[2] http://www.cnblogs.com/java-my-life/archive/2012/04/07/2433939.html