Builder 構建器
動機(Motivation)
- 在軟件系統中,有時候面臨着“一個複雜對象”的創建工作,其通常由各個部分的子對象用一定的算法構成;由於需求的變化,這個複雜對象的各個部分經常面臨着劇烈的變化,但是將它們組合在一起的算法卻相對穩定
- 如何應對這種變化?如何提供一種“封裝機制”來隔離出“複雜對象的各個部分”的變化,從而保持系統中的“穩定構建算法”不隨着需求改變而改變
模式定義
- 將一個複雜對象的構建與其表示相分離,使得同樣的構建過程(穩定)可以創建不同的表示(變化)。
舉個例子
相當於策略方法和工廠方法結合起來。
//主體基類
class House{
//....
};
工廠基類
劇烈的變化,將構建對象時的變化抽象出來(BuildPart1 ~ BuildPart5)
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{
對主體子類初始化
StoneHouseBuilder(House* house) :pHouse(house)
{
}
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(){
執行相應的構建步驟1
pHouseBuilder->BuildPart1();
for (int i = 0; i < 4; i++){
執行相應的構建步驟2
pHouseBuilder->BuildPart2();
}
執行相應的構建步驟3
bool flag=pHouseBuilder->BuildPart3();
if(flag){
執行相應的構建步驟4
pHouseBuilder->BuildPart4();
}
執行相應的構建步驟5
pHouseBuilder->BuildPart5();
返回構建完成的對象
return pHouseBuilder->GetResult();返回構建完成的對象
}
};
結構(Structure)
- 紅色框內爲穩定的部分
- Director爲穩定的構建過程類
- 組合了一個工廠方法的基類 Builder
- 穩定的構建過程 Builder ->BuildPart1 ~ Builder->BuildPart5
- Builder爲工廠方法的基類
- 組合了一個產品基類的指針 *Product
- Director爲穩定的構建過程類
- 藍色框內爲變化的部分
- 具體子類的構建方法 ,override基類Builder的BuildPart1 ~ BuildPart5
- 具體子類的構建方法 ,override基類Builder的BuildPart1 ~ BuildPart5
要點總結
- Builder 模式主要用於“分步驟構建一個複雜的對象”。在這其中“分步驟”是一個穩定的算法,而複雜對象的各個部分則經常變化
- 變化點在哪裏,封裝哪裏—— Builder模式主要在於應對“複雜對象各個部分”的頻繁需求變動。其缺點在於難以應對“分步驟構建算法”的需求變動
- 在Builder模式中,要注意不同語言中構造器內調用虛函數的差別