设计模式学习系列7 建造者模式

概述

        建造者模式,又称生成器模式,将产品内部的表象与产品的生成过程分离,从而可以使用同样的过程或者方法来建造具有不同内部表象的产品对象。使用builder模式后,用户只用指定建造的类型就可以获得他们,而具体的建造过程和细节就不想需要知道了。这里引用另外一个可能比较具体的描述:”在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法确相对稳定。如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的 “稳定构建算法”不随着需求改变而改变?这就是要说的建造者模式。“

模型

clipboard

Director:指挥者,构建一个使用Bulider接口的对象

Bulider:创建Product对象的基类

Product:具体的产品对象,表示被构造的复杂对象。实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并 提供一个检索产品的接口。

ConcreateBulider:具体的建造者,ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口

模式完整的C++代码实例

 
 #include <iostream>
 #include<vector>
 using namespace std;
 
class Product
{
private:
    vector<string> m_Part;
public:
    void Add(const string& str)
    {
        m_Part.push_back(str);
    }
    void Show()
    {
        vector<string>::iterator it  = m_Part.begin();
        for( ; it != m_Part.end() ; ++it)
        {
            cout << (*it) << endl ;    
        }    
    }
};
 
 //抽象建造类 
 class Bulider
 {
public:
    virtual void Create() = 0 ;
     virtual void BulidPartA() = 0;
    virtual void BulidPartB() = 0;
    virtual Product* GetResult() = 0 ;    
 };

//第一种建造类 也就是一种产品 
 class BuliderA:public Bulider
 {
 private:
     Product *p ;                
 public:
     BuliderA()
     {
        p = 0 ;
     }
     ~BuliderA()
     {
         if(p!= 0 )
             delete p ;
    }
    
     void Create()
     {
         p = new Product ;
     }
     void BulidPartA()
     {
         p->Add("BuliderA建造A部分");    
     }
     void BulidPartB()
     {
        p->Add("BuliderA建造B部分");
     }
     Product* GetResult()
     {
         return p ;
     }     
 };
 
//第二种建造类 也就是另外一种产品 
 class BuliderB:public Bulider
 {
 private:
     Product *p ;                
 public:
     BuliderB()
     {
        p = 0 ;
     }
     ~BuliderB()
     {
         if(p!= 0 )
             delete p ;
    }
    
     void Create()
     {
         p = new Product ;
     }
     void BulidPartA()
     {
         p->Add("BuliderB   建造A部分");    
     }
     void BulidPartB()
     {
        p->Add("BuliderB   建造B部分");
     }
     Product* GetResult()
     {
         return p ;    
     }
 };
 
 
 //director部分
 class director
 {
private:
    Bulider* m_bulider ;
public:
    ~director()
    {
        
    }
    
    director(Bulider *_b)
    {    
        m_bulider = _b ; 
    }
    
    void  Ctreate()
    {
        m_bulider->Create();
        m_bulider->BulidPartA();
        m_bulider->BulidPartB();    
    }    
 };
 
 
int main()
{

    BuliderB *pBuliderB = new BuliderB;
    director *pDirector = new director(pBuliderB);    
    
    pDirector->Ctreate();
    
    Product *pProduct = pBuliderB->GetResult();
    pProduct->Show();
    
}
  

Bulider模式简化版本

省略抽象建造者角色

系统中只需要一个具体建造者,省略掉抽象建造者,结构图如下:

PIC046

省略指导者角色

抽象建造者角色已经被省略掉,还可以省略掉指导者角色。让Builder角色自己扮演指导者与建造者双重角色。结构图如下:

PIC047

合并建造者角色和产品角色

建造模式失去抽象建造者角色和指导者角色后,可以进一步退化,从而失去具体建造者角色,此时具体建造者角色和产品角色合并,从而使得产品自己就是自己的建造者。这样做混淆了对象的建造者和对象本身,但是有时候一个产品对象有着固定的几个零件,而且永远只有这几个零件,此时将产品类和建造类合并,可以使系统简单易读。结构图如下:

PIC048

实现要点

1、建造者模式主要用于“分步骤构建一个复杂的对象”,在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。

2、产品不需要抽象类,特别是由于创建对象的算法复杂而导致使用此模式的情况下或者此模式应用于产品的生成过程,其最终结果可能差异很大,不大可能提炼出一个抽象产品类。
3、创建者中的创建子部件的接口方法不是抽象方法而是空方法,不进行任何操作,具体的创建者只需要覆盖需要的方法就可以,但是这也不是绝对的,特别是类似文本转换这种情况下,缺省的方法将输入原封不动的输出是合理的缺省操作。

4、前面我们说过的抽象工厂模式(Abtract Factory)解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化,建造者模式常和组合模式(Composite Pattern)结合使用。

效果

1、建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
2、每一个Builder都相对独立,而与其它的Builder无关。
3、可使对构造过程更加精细控制。

4、将构建代码和表示代码分开。

5、建造者模式的缺点在于难于应付“分步骤构建算法”的需求变动。

适用性

以下情况应当使用建造者模式:

1、需要生成的产品对象有复杂的内部结构。
2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到

 

细雨淅淅 标签:
posted @ 2013-11-07 17:48  RubbyZhang  阅读(326)  评论(0编辑  收藏  举报