Builder

生成器

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
封装一个产品的构造过程,并允许按步骤构造。

适用性

  • 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
  • 当构建过程必须允许被构造的对象有不同的表示时。

示例情境

每个客人的度假计划都不一样,比如天数、活动类型。希望提供一种方式来创建这个复杂的结构,而不会和创建它的步骤混在一起。
Builder Scenario

结构

Builder Class

Builder - 为创建一个Product对象的各个部件指定抽象接口。
ConcreteBuilder - 实现Builder的接口以构造和装配该产品的各个部件。定义并明确它所创建的表示。提供一个检索产品的接口。
Director - 构造一个使用Builder接口的对象。
Product - 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

协作:
客户创建Director对象,并用它所想要的Builder对象进行配置。
一旦产品部件被生成,导向器就会通知生成器。
生成器处理导向器的请求,并将部件添加到该产品中。
客户从生成器中检索产品。
Builder Sequence

示例

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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <iostream>
//---------------------------------------------------
class Product
{
public:
void display()
{

std::cout<<"Product: "<<m_part1<<","<<m_part2<<","<<m_part3<<std::endl;
}
public:
int m_part1;
int m_part2;
int m_part3;
};
//---------------------------------------------------
class Builder
{
public:
virtual void build_part(){}
virtual void build_part1(int part1) {}
virtual void build_part2(int part2) {}
virtual void build_part3(int part3) {}
virtual Product* get_result(){return NULL;}
};
//---------------------------------------------------
class ConcreteBuilderA : public Builder
{
public:
ConcreteBuilderA(): Builder(), m_product(NULL) {}
virtual void build_part()
{

if (!m_product)
{
m_product = new Product();
}
}
virtual Product* get_result()
{

return m_product;
}
void build_part1(int part1)
{

if (!m_product) return;
m_product->m_part1 = part1;
}
void build_part2(int part2)
{

if (!m_product) return;
m_product->m_part2 = part2;
}
void build_part3(int part3)
{

if (!m_product) return;
m_product->m_part3 = part3;
}
public:
Product* m_product;
};
//---------------------------------------------------
class ConcreteBuilderB : public Builder
{
public:
ConcreteBuilderB(): Builder(), m_product(NULL) {}
virtual void build_part()
{

if (!m_product)
{
m_product = new Product();
}
}
virtual Product* get_result()
{

return m_product;
}
void build_part1(int part1)
{

if (!m_product) return;
m_product->m_part1 = part1 * 10;
}
void build_part2(int part2)
{

if (!m_product) return;
m_product->m_part2 = part2 * 10;
}
void build_part3(int part3)
{

if (!m_product) return;
m_product->m_part3 = part3 * 10;
}
public:
Product* m_product;
};
//---------------------------------------------------
class Director
{
public:
Product* construct(Builder& builder)
{

builder.build_part();
builder.build_part1(1);
builder.build_part2(2);
builder.build_part3(3);
return builder.get_result();
}
};
//---------------------------------------------------
int main()
{

Product* product;
Director director;
ConcreteBuilderA builderA;
ConcreteBuilderB builderB;

director.construct(builderA);
product = builderA.get_result();
product->display();
delete product;
product = NULL;

director.construct(builderB);
product = builderB.get_result();
product->display();
delete product;
product = NULL;
system("Pause");
}

优点

  • 将一个复杂对象的创建过程封装起来。
  • 允许对象通过多个步骤来创建,并且可以改变过程(这和只有一个步骤的工厂模式不同)。
  • 向客户隐藏产品内部的表现。
  • 产品的实现可以被替换,因为客户只看到一个抽象的接口。

用途和缺点

  • 经常被用来创建组合结构。
  • 与工厂模式相比,采用生成器模式创建对象的客户,需要具备更多的领域知识。

相关模式

  • Abstract Factory与Builder相似,因为它也可以创建复杂对象。主要的区别是Builder着重于一步步构造一个复杂对象,而Abstract Factory着重于多个系列的产品对象(简单的或是复杂的)。Builder在最后一步返回产品,而对于Abstract Factory来说,产品是立即返回的。
  • Composite通常是用Builder生成的。

[1] 设计模式:可复用面向对象软件的基础
[2] Head First 设计模式