1. 程式人生 > >【設計模式】建造者模式

【設計模式】建造者模式

object lan pat alt pri 創建對象 private 關心 turn

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();

    return 0;
}

3、優缺點

● 封裝性
使用建造者模式可以使客戶端不必知道產品內部組成的細節。
● 建造者獨立, 容易擴展
各個Builder是相互獨立的, 對系統的擴展非常有利。
● 便於控制細節風險
由於具體的建造者是獨立的, 因此可以對建造過程逐步細化, 而不對其他的模塊產生任何影響。

4、使用場景

● 相同的方法, 不同的執行順序, 產生不同的事件結果時, 可以采用建造者模式。
● 多個部件或零件, 都可以裝配到一個對象中, 但是產生的運行結果又不相同時, 則可以使用該模式。
● 產品類非常復雜, 或者產品類中的調用順序不同產生了不同的效能, 這個時候使用建造者模式非常合適。
● 在對象創建過程中會使用到系統中的一些其他對象, 這些對象在產品對象的創建過程中不易得到時, 也可以采用建造者模式封裝該對象的創建過程。 該種場景只能是一個補償方法, 因為一個對象不容易獲得, 而在設計階段竟然沒有發覺, 而要通過創建者模式柔化創建過程, 本身已經違反設計的最初目標。

5、Builder VS AbstractFactory

建造者模式最主要的功能是基本方法的調用順序安排, 也就是這些基本方法已經實現了, 通俗地說就是零件的裝配, 順序不同產生的對象也不同; 而工廠方法則重點是創建, 創建零件是它的主要職責, 組裝順序則不是它關心的。

Builder模式強調的是一步步創建對象,並通過相同的創建過程可以獲得不同的結果對象,一般來說Builder模式中對象不是直接返回的。而在AbstractFactory模式中對象是直接返回的,AbstractFactory模式強調的是為創建多個相互依賴的對象提供一個同一的接口。

【設計模式】建造者模式