The Programming world of Alex

设计模式之Builder模式

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



 

posted on 2009-04-14 21:51 Alex@VCC 阅读(2359) 评论(1)  编辑 收藏 引用 所属分类: 设计模式

评论

# re: 设计模式之Builder模式 2009-04-15 14:28 yleesun

学习...  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


<2009年4月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

导航

统计

常用链接

留言簿(5)

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜