设计模式---对象创建模式之构建器模式(Builder)

Posted ssyfj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式---对象创建模式之构建器模式(Builder)相关的知识,希望对你有一定的参考价值。

一:概念

Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种。Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。
对象的创建:Builder模式是为对象的创建而设计的模式

创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象

关注对象创建的各部分的创建过程:不同的工厂(这里指builder生成器)对产品属性有不同的创建方法。

二:动机

在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将他们组合在一起的算法却相对稳定
如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变。

三:代码解析(建造房子)

class House{
    //....

     House(){ // 错误示例,不能这样写

        this->BuildPart1(); // 构造函数中是静态绑定,此时调用纯虚函数会报错,不会去调用子类

        for (int i = 0; i < 4; i++){
            this->BuildPart2();
        }

        bool flag = pHouseBuilder->BuildPart3();

        if (flag){
            this->BuildPart4();
        }

        this->BuildPart5();
    }

    void Init(){ // 流程相对固定

        this->BuildPart1(); // 构造第一部分

        for (int i = 0; i < 4; i++){
            this->BuildPart2();
        }

        bool flag = pHouseBuilder->BuildPart3();

        if (flag){
            this->BuildPart4();
        }

        this->BuildPart5();        
    }
    virtual ~HouseBuilder(){}
protected:    
    virtual void BuildPart1() = 0;
    virtual void BuildPart2() = 0;
    virtual void BuildPart3() = 0;
    virtual void BuildPart4() = 0;
    virtual void BuildPart5() = 0;
};
C++构造函数中,是不会去调用子类的虚函数。
子类构造函数会先去调用父类构造函数,如果子类调用父类构造,父类构造中去寻找子类虚函数,会报错,因为子类构造函数还没有完成,子类虚函数先被调用,这违背对象的构造原理
class StoneHouse: public House{  //各种房子

protected:

    virtual void BuildPart1(){
        //pHouse->Part1 = ...;
    }
    virtual void BuildPart2(){

    }
    virtual void BuildPart3(){

    }
    virtual void BuildPart4(){

    }
    virtual void BuildPart5(){

    }
};

四:模式定义

  将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)。

                                              --《设计模式》Gof   
Init就是同一个构建过程,而每一个对象我们只需要实现其构建步骤就可以创建不同的表示
int main()
{
    House* pHouse = new StoneHouse();
    pHouse->Init();
}

五:进一步优化(对象过于复杂,除了上面步骤还有其他方法和属性)

class House{ // 表示  抽象基类
    //.... house 与 HouseBuilder 相分离
};

class HouseBuilder {  // 构建  抽象基类
public:
    House* GetResult(){
        return pHouse;
    }
    virtual ~HouseBuilder(){}
protected:
    
    House* pHouse;
    virtual void BuildPart1()=0;
    virtual void BuildPart2()=0;
    virtual void BuildPart3()=0;
    virtual void BuildPart4()=0;
    virtual void BuildPart5()=0;
    
};

class StoneHouse: public House{
    
};

class StoneHouseBuilder: public HouseBuilder{
protected:
    
    virtual void BuildPart1(){
        //pHouse->Part1 = ...;
    }
    virtual void BuildPart2(){
        
    }
    virtual void BuildPart3(){
        
    }
    virtual void BuildPart4(){
        
    }
    virtual void BuildPart5(){
        
    }
    
};

// 稳定
class HouseDirector{  // 同样的构建过程
    
public:
    HouseBuilder* pHouseBuilder;
    
    HouseDirector(HouseBuilder* pHouseBuilder){
        this->pHouseBuilder=pHouseBuilder;
    }
    
    House* Construct(){
        
        pHouseBuilder->BuildPart1();
        
        for (int i = 0; i < 4; i++){
            pHouseBuilder->BuildPart2();
        }
        
        bool flag=pHouseBuilder->BuildPart3();
        
        if(flag){
            pHouseBuilder->BuildPart4();
        }
        
        pHouseBuilder->BuildPart5();
        
        return pHouseBuilder->GetResult();
    }
};
HouseBuilder管构建,House将其分离出去,而创建步骤又是稳定的,我们再一步进行拆分为HouseDiretor,避免类的肥大

六:类图(结构)

技术分享图片

类复杂就拆分,类简单就合并

七:要点总结

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

(二)变化的点在哪里,封装哪里——Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动。

(三)在Builder模式中,要注意不同语言中构造器内调用虚函数的差别(C++ vs. C#)。

八:构建器和工厂模式区别

(一)Factory模式中:

1.有一个抽象的工厂。
2.实现一个具体的工厂---汽车工厂。
3.工厂生产汽车A,得到汽车产品A。
4.工厂生产汽车B,得到汽车产品B。
这样做,实现了购买者和生产线的隔离。

(二)Builder模式:

1.离合器工厂生产离合器产品,得到汽车部件A。
2.轮胎工厂生产轮子产品,得到汽车部件B。
3.车身工厂生产车身产品,得到汽车部件C。
4.将这些部件放到一起,形成刚好能够组装成一辆汽车的整体。
5.将这个整体送到汽车组装工厂,得到一个汽车产品。
或者更抽象一点理解:
1.将汽车的每一个零件都送到汽车组装工厂。
2.在工厂里,组装离合器,得到汽车部件A。
3.在工厂里,组装轮胎,得到汽车部件B。
4.在工厂里,组装车身,得到汽车部件C。
5.在工厂里,组装每个部件,得到一个汽车产品。
这样做,目的是为了实现复杂对象生产线和其部件的解耦。

(三)二者不同在于:

Factory模式不考虑对象的组装过程,而直接生成一个我想要的对象。
Builder模式先一个个的创建对象的每一个部件,再统一组装成一个对象。
Factory模式所解决的问题是,工厂生产产品。而Builder模式所解决的问题是工厂控制产品生成器组装各个部件的过程,然后从产品生成器中得到产品。

九:案例实现(建房子)

(一)实现抽象类Director(工程师),House(房子),HouseBuilder(工程队)

 

class House
{
private:
    string m_floor;
    string m_wall;
    string m_door;
public:
    void setFloor(string floor)
    {
        this->m_floor = floor;
    }

    void setWall(string wall)
    {
        this->m_wall = wall;
    }

    void setDoor(string door)
    {
        this->m_door = door;
    }

    void getFloor()
    {
        cout << "install " << this->m_floor << endl;
    }

    void getWall()
    {
        cout << "install " << this->m_wall << endl;
    }

    void getDoor()
    {
        cout << "install " << this->m_door << endl;
    }
};

class HouseBuilder
{
protected:
    House* pHouse;

public:
    virtual void BuildFloor() = 0;
    virtual void BuildWall() = 0;
    virtual void BuildDoor() = 0;

    House* GetResult()
    {
        return pHouse;
    }
};

class HouseDirector
{
public:
    HouseBuilder* pHouseBuilder;

    HouseDirector(HouseBuilder* pHouseBuilder)
    {
        this->pHouseBuilder = pHouseBuilder;
    }

    House* Construct()
    {
        pHouseBuilder->BuildWall();
        pHouseBuilder->BuildFloor();
        pHouseBuilder->BuildDoor();
        return pHouseBuilder->GetResult();
    }
};

(二)实现具体房子类和建造类

class StoneHouseBuilder :public HouseBuilder
{
public:
    StoneHouseBuilder()
    {
        pHouse = new House();
    }

    virtual void BuildFloor()
    {
        pHouse->setFloor("stone floor");
    }

    virtual void BuildWall()
    {
        pHouse->setWall("stone wall");
    }

    virtual void BuildDoor()
    {
        pHouse->setDoor("stone door");
    }
};

class FlatHouseBuilder :public HouseBuilder
{
public:
    FlatHouseBuilder()
    {
        pHouse = new House();
    }

    virtual void BuildFloor()
    {
        pHouse->setFloor("flat floor");
    }

    virtual void BuildWall()
    {
        pHouse->setFloor("flat wall");
    }

    virtual void BuildDoor()
    {
        pHouse->setFloor("flat door");
    }
};

(三)工程师步骤指挥,按步骤创建房屋

void main()
{
    HouseBuilder* HB = new StoneHouseBuilder();
    HouseDirector* HD = new HouseDirector(HB);
    House* H = HD->Construct();

    H->getWall();
    H->getFloor();
    H->getDoor();

    delete H;
    delete HB;
    delete HD;

    system("pause");
    return;
}

技术分享图片

 

以上是关于设计模式---对象创建模式之构建器模式(Builder)的主要内容,如果未能解决你的问题,请参考以下文章

GOF之构建器模式

设计模式之:对象创建模式

(建造者模式)链式编程之 @Builder 和 @Accessors 学习

Spring:使用构建器模式创建 bean

Java设计模式之建造者模式(Builder Pattern)

Java设计模式之建造者模式(Builder Pattern)