Builder模式仍然属于创建型模式,主要体现了OO中“封装”和“多态”两个特性。
还是引一个简单的例子来说明Builder模式的意义。
假设我们设计的游戏中需要创建一个比较复杂的房屋对象,房屋对象有很多部分组成,比如说有门,窗户,墙,地板等等。当我们在将这个房屋实现之后,可能随着需求的改变需要对门进行更换,将原来的木门换成铁门。这时候的问题就是:如何改变组成部分而对房屋整体不做改变?
到了这里就需要我们对房屋进行抽象:房屋拥有门,窗户,墙等部分,这些部分可能容易发生变化。房屋也有其稳定的结构,这结构就是如何将门,窗户,墙等部分如何连接起来的算法。
上图中引入了Builder这一概念,我们可以把他理解成为生产各个部件(如门,窗户)的一个生成器(有点像之前说的工厂,但又不完全是),代码中具体将其实现成为抽象类。红线以上是相对稳定的部分,红线以下是相对易变的部分。其中构建算法(即如何连接房屋中各个部件间的关系)稳定,但部件类型依赖于Builder,Builder具体实现为何种方案(木门还是铁门?)这全由多态的动态绑定机制决定(即交由客户代码来决定)。
动机:
软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临剧烈变化,但将其组合在一起的算法却相对稳定。
意图:
将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。(GoF)
GoF给出的这个意图相当的晦涩难懂,关键就在“同样的构建过程”和“不同的表示”。“同样的构建过程”就是指前面分析中的稳定构建算法;“不同的表示”就是不同部件组合出来的不同的对象。
设计思路:
先看UML图
图中Director使用Builder的对象,他的Construct方法就是“意图”中所指的“同样的构建过程”,即对象的稳定构建算法。Builder作为参数传入Construct以提供具体的对象对象。
而Builder类作为接口实现,提供Product中各个部件的生成接口;ConcreteBuilder来对接口具体实现,并有一个返回具体Product的方法GetResult。
上图描述了客户程序,Director类,ConcreteBuilder类如何进行协作。首先客户代码确定需要何种类型的对象,创建相应的ConcreteBuilder;再创建Director类,将ConcreteBuilder作为参数传入;在Construct方法中创建对象中A,B,C三个子部分,并对这些子部分进行合理的组织;最后通过ConcreteBuilder的GetResult方法获得所需对象。
Builder模式和Abstract Factory模式很容易让人混淆,因为他们都可以产生不同系列的对象。
但是两者还是有本质差别的:
1.两者目的不同。Builder模式是为了产生单个复杂对象;Abstract Factory模式是为了产生一系列不同风格的对象。(Builder模式也产生一系列对象,但他们都是复杂对象的子部分)
2.Builder模式在最后一步返回对象;Abstract Factory模式中的系列对象是立即返回的。
自己实现的示例代码,仅供参考:
Main.cpp
1/**/////////////////////////////////////////////////////////////////////////// 2// BuilderTest for Builder Pattern Test
3//
4/**/////////////////////////////////////////////////////////////////////////// 5
6#include "stdafx.h"
7#include "AbstractInfo.h"
8#include "Builder.h"
9#include "ModernHouse.h"
10#include "Castle.h"
11#include <iostream>
12using namespace std;
13
14//对应UML图中的Director类
15class HouseManager
16{
17public:
18 //对House中的子部件进行组装,该部分被认为相对稳定
19 void construct(Builder* builder)
20 {
21 builder->buildDoor();
22 builder->buildWindow();
23 builder->buildWall();
24 builder->buildFloor();
25 builder->buildCeiling();
26 }
27};
28
29int _tmain(int argc, _TCHAR* argv[])
30{
31 //创建ConcreteBuilder
32 Builder* builder = new CastleBuilder();
33 //HouseManager对应Director,construct方法对House的子部件(门,窗户等)进行组装
34 HouseManager* houseManager = new HouseManager();
35 houseManager->construct(builder);
36 //得到需要的结果(Castle)
37 House* house = builder->getResult();
38
39 delete house;
40 delete houseManager;
41 delete builder;
42 return 0;
43}
各种抽象类,包括房屋,门,窗户。。。
AbstracInfo.h
1#pragma once
2
3class Door
4{
5protected:
6 Door(){}
7};
8
9class Window
10{
11protected:
12 Window(){}
13};
14
15class Wall
16{
17protected:
18 Wall(){}
19};
20
21class Floor
22{
23protected:
24 Floor(){}
25};
26
27class Ceiling
28{
29protected:
30 Ceiling(){}
31};
32
33class House
34{
35protected:
36 House(Door* d,Window* wd,Wall* wl,Floor* f,Ceiling* c){}
37};
38
39
Builder.h
1#pragma once
2#include "AbstractInfo.h"
3
4class Builder
5{
6public:
7 virtual void buildDoor() = 0;
8 virtual void buildWindow() = 0;
9 virtual void buildWall() = 0;
10 virtual void buildFloor() = 0;
11 virtual void buildCeiling() = 0;
12 virtual House* getResult() = 0;
13};
14
15
Castle.h
1#pragma once
2#include "AbstractInfo.h"
3#include "Builder.h"
4#include <iostream>
5using namespace std;
6
7class Castle : public House
8{
9public:
10 Castle(Door* d,Window* wd,Wall* wl,Floor* f,Ceiling* c)
11 :House(d,wd,wl,f,c)
12 {
13 cout<<"Create a Castle with Door, Window, Wall, Floor, Ceiling"<<endl;
14 }
15};
16
17class CastleDoor : public Door
18{
19public:
20 CastleDoor()
21 {
22 cout<<"the Castle Door is created"<<endl;
23 }
24};
25
26class CastleWindow : public Window
27{
28public:
29 CastleWindow()
30 {
31 cout<<"the Castle Window is created"<<endl;
32 }
33};
34
35class CastleWall : public Wall
36{
37public:
38 CastleWall()
39 {
40 cout<<"the Castle Wall is created"<<endl;
41 }
42};
43
44class CastleFloor : public Floor
45{
46public:
47 CastleFloor()
48 {
49 cout<<"the Castle Floor is created"<<endl;
50 }
51};
52
53class CastleCeiling : public Ceiling
54{
55public:
56 CastleCeiling()
57 {
58 cout<<"the Castle Ceiling is created"<<endl;
59 }
60};
61
62class CastleBuilder : public Builder
63{
64private:
65 Door* door;
66 Window* window;
67 Wall* wall;
68 Floor* floor;
69 Ceiling* ceiling;
70public:
71 void buildDoor()
72 {
73 door = new CastleDoor();
74 }
75 void buildWindow()
76 {
77 window = new CastleWindow();
78 }
79 void buildWall()
80 {
81 wall = new CastleWall();
82 }
83 void buildFloor()
84 {
85 floor = new CastleFloor();
86 }
87 void buildCeiling()
88 {
89 ceiling = new CastleCeiling();
90 }
91 Castle* getResult()
92 {
93 return new Castle(door,window,wall,floor,ceiling);
94 }
95 ~CastleBuilder()
96 {
97 if (door != NULL) { delete door;}
98 if (window != NULL) { delete window;}
99 if (wall != NULL) { delete wall;}
100 if (floor != NULL) { delete floor;}
101 if (ceiling != NULL) { delete ceiling;}
102 }
103};
104