設計模式---對象創建模式之構建器模式(Builder)
阿新 • • 發佈:2018-08-26
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)