1. 程式人生 > >設計模式---對象創建模式之構建器模式(Builder)

設計模式---對象創建模式之構建器模式(Builder)

out ++ 生成 構造器 build 創建過程 隱藏 spa col

一:概念

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)