Builder
動機
- 有時候面臨着“一個複雜對象”的創建工作,其通常由各個部分的子對象用一定的算法構成;由於需求的變化,這 個複雜對象的各個部分經常面臨着劇烈的變化,但是將它們組合在一起的算法卻相對穩定。
- 如何應對這種變化?如何提供一種“封裝機制”來隔離出“複雜對象的各個部分”的變化,從而保持系統中的“穩定構建算法”不隨着需求改變而改變?
模式定義
將一個複雜對象的構建與其表示相分離,使得同樣的構建過程(穩定)可以創建不同的表示(變化)。 ——《設計模式》GoF
要點總結
- Builder 模式主要用於“分步驟構建一個複雜的對象”。在這其中**“分步驟”是一個穩定的算法**,而複雜對象的各個部分則經常變化。
- 變化點在哪裏,封裝哪裏—— Builder模式主要在於應對“複雜對象各個部分”的頻繁需求變動。其缺點在於難以應對“分步驟構建算法”的需求變動。
- 在Builder模式中,要注意不同語言中構造器內調用虛函數的差別(C++(構造函數中不可以調用虛函數) vs. C#、Java(可以))。
Demo
class House{
//....
//1.其中建房子的步驟應寫在一個init函數裏,不能寫在構造函數裏;
//構造函數調用虛函數是靜態綁定
//2.如果建房子的步驟太複雜,造成類太肥,則將建房子步驟抽離到HouseDirector類裏
};
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與HouseDirector寫在一起也沒什麼問題,主要看類的複雜程度,如果太複雜則抽離抽離抽離…