1、意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
2、别名
无
3、为什么会使用Builder模式
在使用Word的时候,我们可以将文档存为多种格式,如RTF、txt、doc等等。假设我们在转换过程中是根据不同的元素来进行转化的,比如可以将转换分为字母转换、字体转换和段落标记的转换,且每次转换都会有这三个步骤。而且,未来可能还需要加入我们目前仍然未知的格式。则这里很显然我们可以抽象出这三个步骤的接口,并在其子类中实现;然后将这三个部分组合起来,就成为了我们所需要的东西。这样的一种方法便被称为了Builder模式。
4、适用性
以下情况下可以使用此模式:
• 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
• 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
5、实例
我们仍然沿用前面的迷宫例子:我们现在需要一个这样的标准迷宫:它只有两个相邻的房间,编号为1的房间东面是一扇门,这扇门是与编号为2的房间共用的,其他的面都为墙壁。
6、结构图示
我们现在使用Builder模式来创建它,首先看结构图示:
在这里,抽象类MazeBuilder称为builder,它创建了一套公共的接口,指出了构建一个迷宫所需要的操作并提供了一个检索产品的方法;但真正的实现部分是在下面继承自它的StandardMazeBuilder子类中。里面的MazeGame又称为director,因为它负责构造一个使用builder的对象。这里的Product显然就是Maze了,它由StandardMazeBuilder装配而成。
7、协作关系
• 首先是客户创建director,并配置所需要的builder的部件。
• 一旦需要产品部件,director会给builder一个通知。
• builder会检索如何去实现director的需求,生成部件并添加到产品。
• 最终客户从builder中去检索所需要的产品。
如下图
8、代码实现
这里仅仅作些示例代码,希望需要全部代码的可在文章最后的链接处下载。
首先看builder的定义,上面的结构图已经清晰的指出它是一个抽象类。
{
protected MazeBuilder()
{
}
public abstract void BuildMaze();
public abstract void BuildRoom(int roomNo);
public abstract void BuildDoor(int roomFrom, int roomTo);
public abstract Maze GetMaze();
}
再来看看director,它定义了需要什么样的产品并返回所生成的产品。
{
public MazeGame()
{
}
public Maze CreateMaze(MazeBuilder builder)
{
builder.BuildMaze();
builder.BuildRoom(1);
builder.BuildRoom(2);
builder.BuildDoor(1, 2);
return builder.GetMaze();
}
}
客户只需简单创建director就可以得到所构建的产品
StandardMazeBuilder builder = new StandardMazeBuilder();
game.CreateMaze(builder);
Maze maze = builder.GetMaze();
9、使用builder模式的效果
1)它让你可以改变一个产品的内部表示。因为你总是需要通过director来调用抽象出来的builder接口。
2)构造代码与表示代码分开了。举个例子:如果你有个产品是由A、B、C三部分生成,但B有两种不同的实现而造成有两种产品。那么对于A和C你仍然只需要写一次代码,然后通过配置director而得到不同的产品。
3)你可以更精确的控制如何构造产品。由于产品是一部一部构建起来的,因此你可以决定构建的顺序并控制其内部结构。
10、相关模式
Abstract Factory与Builder相似,他们都可以创建复杂对象。主要区别就是builder着重一步步构造复杂的产品对象,而Abstract Factory着重生成一个系列的产品对象。另外一个就是builder是最后才返回产品,而Abstract Factory则立即返回。
Composite通常由Builder生成。