• 【设计模式】建造者模式


    1、定义

    1.1 标准定义

      建造者模式( Builder Pattern) 也叫做生成器模式, 其定义如下:

      Separate the construction of a complex object from its representation so that the same construction process can create different representations.( 将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示。 )

    1.2  通用类图

      在建造者模式中, 有如下4个角色:

      ● Product产品类
      通常是实现了模板方法模式, 也就是有模板方法和基本方法, 参考模板方法模式。

      ● Builder抽象建造者
      规范产品的组建, 一般是由子类实现。

      ● ConcreteBuilder具体建造者
      实现抽象类定义的所有方法, 并且返回一个组建好的对象。

      ● Director导演类
      负责安排已有模块的顺序。

    2、实现

    2.1 类图

      Builder:定义创建对象过程的抽象,提供构建不同组成部分的接口

      其中:BuildPartA,BuildPartB,BuildPartC是对一个对象不同部分的构建函数接口,由Builder的派生类ConcreteBuilder1、ConcreteBuilder2来具体实现。

      另外还有一个需要注意的函数,就是Director::Construct函数,这个函数里面通过调用上面的接口函数完成对象的构建--也就是说各个不同部分装配的过程都是一致的(同样的调用的Construct函数),但是不同的构建方式会有不同的表示(根据Builder的实际类型来决定如何构建,也就是多态)。

      Builder模式是基于这样的一个情况:一个对象可能有不同的组成部分,这几个部分的不同的创建对象会有不同的表示,但是各个部分之间装配的方式是一致的.比方说一辆单车,都是由车轮车座等等的构成的(一个对象不同的组成部分),不同的品牌生产出来的也不一样(不同的构建方式).虽然不同的品牌构建出来的单车不同,但是构建的过程还是一样的。

      也就是说,Director::Construct函数中固定了各个组成部分的装配方式,而具体是装配怎样的组成部分由Builder的派生类实现.

    2.2 代码

    2.2.1 建造者

    //builder.h
    
    #ifndef _BUILDER_H_
    #define _BUILDER_H_
    
    #include <string>
    #include <vector>
    
    using namespace std;
    
    //产品类
    class Product
    {
    private:
        string m_partA;
        string m_partB;
        string m_partC;
    public:
        void setPartA(const string& s);
        void setPartB(const string& s);
        void setPartC(const string& s);
        Product();
        ~Product();
    };
    
    //抽象Builder基类,定义不同部分的创建接口
    class Builder
    {
    public:
        virtual void BuildPartA()=0;
        virtual void BuildPartB()=0;
        virtual void BuildPartC()=0;
        virtual Product* GetProduct()=0;
        Builder();
        virtual ~Builder();
    };
    
    //  Builder的派生类,实现BuilderPartA和BuilderPartB和BuildPartC接口函数 
    class ConcreteBuilder1:public Builder
    {
    public:
        ConcreteBuilder1();
        ~ConcreteBuilder1();
        virtual void BuildPartA();
        virtual void BuildPartB();
        virtual void BuildPartC();
        virtual Product* GetProduct();
    private:
        Product* m_pProduct;
    };
    
    //  Builder的派生类,实现BuilderPartA和BuilderPartB和BuildPartC接口函数 
    class ConcreteBuilder2:public Builder
    {
    public:
        ConcreteBuilder2();
        ~ConcreteBuilder2();
        virtual void BuildPartA();
        virtual void BuildPartB();
        virtual void BuildPartC();
        virtual Product* GetProduct();
    private:
        Product* m_pProduct;
    };
    
    //ConcreteBuilder1与ConcreteBuilder2是Builder的两个派生类,用于实现两种不同的建造细节
    
     // 使用Builder构建产品,构建产品的过程都一致,但是不同的builder有不同的实现
     // 这个不同的实现通过不同的Builder派生类来实现,存有一个Builder的指针,通过这个来实现多态调用 
    class Director
    {
    public:
        Director(Builder* pBuilder);
        ~Director();
    
        //Construct函数定义一个对象的整个构建过程,不同的部分之间的装配方式都是一致的,
        //首先构建PartA其次是PartB,只是根据不同的构建者会有不同的表示 
        void Construct();
        //void Construct(const string& buildPara);
    private:
        Builder* m_pBuilder;
    };
    
    #endif
    //builder.cpp
    
    #include "Builder.h"
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    Product::~Product(){}
    
    Product::Product(){}
    
    void Product::setPartA(const string& s)
    {
        this->m_partA = s;
    }
    
    void Product::setPartB(const string& s)
    {
        this->m_partB = s;
    }
    
    void Product::setPartC(const string& s)
    {
        this->m_partC = s;
    }
    
    //--------------------------------------------
    
    Builder::Builder(){}
    
    Builder::~Builder(){}
    
    //--------------------------------------------
    
    ConcreteBuilder1::ConcreteBuilder1()
    {
        this->m_pProduct = new Product();
        cout<<"Create empty product!"<<endl;
    }
    
    void ConcreteBuilder1::BuildPartA()
    {
        this->m_pProduct->setPartA("A");
        cout<<"BuildPartA"<<endl;
    }
    
    void ConcreteBuilder1::BuildPartB()
    {
        this->m_pProduct->setPartB("B");
        cout<<"BuildPartB"<<endl;
    }
    
    void ConcreteBuilder1::BuildPartC()
    {
        this->m_pProduct->setPartC("C");
        cout<<"BuildPartC"<<endl;
    }
    
    Product* ConcreteBuilder1::GetProduct()
    {
        return this->m_pProduct;
    }
    
    ConcreteBuilder1::~ConcreteBuilder1()
    {
        delete this->m_pProduct;
        this->m_pProduct = NULL;
    }
    
    //--------------------------------------------
    
    ConcreteBuilder2::ConcreteBuilder2()
    {
        this->m_pProduct = new Product();
        cout<<"Create empty product!"<<endl;
    }
    
    void ConcreteBuilder2::BuildPartA()
    {
        this->m_pProduct->setPartA("A");
        cout<<"BuildPartA"<<endl;
    }
    
    void ConcreteBuilder2::BuildPartB()
    {
        this->m_pProduct->setPartB("B");
        cout<<"BuildPartB"<<endl;
    }
    
    void ConcreteBuilder2::BuildPartC()
    {
        this->m_pProduct->setPartC("C");
        cout<<"BuildPartC"<<endl;
    }
    
    Product* ConcreteBuilder2::GetProduct()
    {
        return this->m_pProduct;
    }
    
    ConcreteBuilder2::~ConcreteBuilder2()
    {
        delete this->m_pProduct;
        this->m_pProduct = NULL;
    }
    
    //--------------------------------------------
    
    Director::Director(Builder* pBuilder)
    {
        this->m_pBuilder = pBuilder;
    }
    
    void Director::Construct()
    {
        this->m_pBuilder->BuildPartA();
        this->m_pBuilder->BuildPartB();
        this->m_pBuilder->BuildPartC();
    }
    
    Director::~Director()
    {
        delete this->m_pBuilder;
        this->m_pBuilder = NULL;
    }

    2.2.3 调用

    //main.cpp
    
    #include "Builder.h"
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        Director* pDirector = new Director(new ConcreteBuilder1());
        pDirector->Construct();
    
        Director* pDirector1 = new Director(new ConcreteBuilder2());
        pDirector1->Construct();
        
        delete pDirector;
        pDirector = NULL;
        
        delete pDirector1;
        pDirector1 = NULL;
    
        return 0;
    }

    3、优缺点

      ● 封装性
      使用建造者模式可以使客户端不必知道产品内部组成的细节。

      ● 建造者独立, 容易扩展
      各个Builder是相互独立的, 对系统的扩展非常有利。

      ● 便于控制细节风险
      由于具体的建造者是独立的, 因此可以对建造过程逐步细化, 而不对其他的模块产生任何影响。

    4、使用场景

      ● 相同的方法, 不同的执行顺序, 产生不同的事件结果时, 可以采用建造者模式。
      ● 多个部件或零件, 都可以装配到一个对象中, 但是产生的运行结果又不相同时, 则可以使用该模式。
      ● 产品类非常复杂, 或者产品类中的调用顺序不同产生了不同的效能, 这个时候使用建造者模式非常合适。

    5、Builder VS AbstractFactory

      建造者模式最主要的功能是基本方法的调用顺序安排, 也就是这些基本方法已经实现了, 通俗地说就是零件的装配, 顺序不同产生的对象也不同; 而工厂方法则重点是创建, 创建零件是它的主要职责, 组装顺序则不是它关心的。

      Builder模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说Builder模式中对象不是直接返回的。而在AbstractFactory模式中对象是直接返回的,AbstractFactory模式强调的是为创建多个相互依赖的对象提供一个同一的接口。

  • 相关阅读:
    Git本地仓库push至GitHub远程仓库每次输入账户密码问题解决(亲测可行)
    Laravel5.5+ 区分前后端用户登录
    word 中Sentences、Paragraph等含义和用法
    Word转图片word
    Word文档编号工具,Word标题,图、表手动编号工具
    Word电子扫描器 Word文档转换为图片Pdf,Word文档扫描成Pdf工具
    如何用vba给一个word表格的最后插入一行
    PPT电子扫描仪 ppt转换为图片Pdf工具
    Word文档只读加密工具
    在c#应用程序中使用IrisSkin2.dll美化界面
  • 原文地址:https://www.cnblogs.com/ChinaHook/p/7219893.html
Copyright © 2020-2023  润新知