標籤:
builder模式,即建造者模式,和前面的工廠一樣都是用於解決對象建立的問題。
意圖:
將一個複雜物件的構建與它的實現分離,使得同樣的構建過程可以建立不同的表示。
問題拋出,什麼是複雜物件的構建過程。
代碼:
class Car{public: void Init() //構造 { this->designPrototype(); for (int i = 0; i < 4; i++) { this->wheelInstall(i); } this->smartInit(); this->systemTest(); }protected: virtual void designPrototype()=0; virtual void wheelInstall(int)=0; virtual void smartInit()=0; virtual void systemTest()=0;};
這裡沒有把構造過程放進建構函式,是因為建構函式中無法動態綁定this,原因:子類建構函式會先調用父類的建構函式,而父類建構函式執行到動態綁定的語句時,與通過this的虛函數表(如果不知道要研究下了)查詢相應的函數,而此時子類還未初始化完成,所以會拋出錯誤。
init()為對象構建過程,在這裡該過程具有穩定性。
class Ferrari :public Car{ string _name = "Ferrari"; virtual void designPrototype(); virtual void wheelInstall(int); virtual void smartInit(); virtual void systemTest();public: void sayName() { cout << _name << endl; } Ferrari(){ Car::Init(); }};void Ferrari::designPrototype(){ this->_name = "Ferrari"; cout << "設計汽車原型中。。。" << endl; //實際實現代碼。。。 cout << "原型設計完畢,準備進入下一階段" << endl;}void Ferrari::wheelInstall(int time){ cout << "初始化第" << time << "個輪子" << endl; cout << "組裝中" << endl; //實現代碼,比如輪子類 cout << "輪子組裝完畢,進入下一階段" << endl;}void Ferrari::smartInit(){ cout << "機動層初始化" << endl; cout << "機動層正常,進入下一階段" << endl;}void Ferrari::systemTest(){ cout << "汽車效能測試" << endl; cout << "安全性測試" << endl; cout << "試跑正常" << endl; cout << "構建成功" << endl;}
測試:
好像,這樣子已經可以很大程度上滿足我們的需求了,而且結果似乎很完美。
builder模式的結構是怎麼樣的呢。
結構圖:
其實就是把我們上面的一個大類,分成了director,builder,和product(它本身),director複製init工作,builder複製每一個小步驟,於是director是一個穩定的類,car的構建過程是相對穩定的,而builder是變化莫測的,因為它的每一步都可能是變化的,至少我們上面的代碼,就是是輪子組裝這一塊,如果我們還有一個輪子類,那麼我還是想象,法拉利和寶馬的輪子應該是不一樣的,輪子構造過程應該也可以是變化的,當然這種假設是抽象的,只是為了迎合這樣一個模式,完全不用太較真。
所以用builder模式應該是:
產品職責變少:
class Car{string _name;public: virtual ~Car(){} virtual void sayName(){ cout << _name << endl; } string getName(){ return _name; } void setName(string name){ _name = name; }};
class Ferrari :public Car{public: void sayName() { cout << "i m a car,my name is:" << getName() << endl; }};
builder:
class CarBulider{protected: Car * _car; virtual void designPrototype() = 0; virtual void wheelInstall(int) = 0; virtual void smartInit() = 0; virtual void systemTest() = 0; virtual Car* getResult(){ return _car; }; friend class Director;public: virtual ~CarBulider(){}};
concrete builder:
class FerrariBulider :public CarBulider{ virtual void designPrototype(); virtual void wheelInstall(int); virtual void smartInit(); virtual void systemTest();public: FerrariBulider(){ }};void FerrariBulider::designPrototype(){ cout << "設計汽車原型中。。。" << endl; //實際實現代碼。。。 CarBulider::_car = new Ferrari(); //這裡建立對象,它將由客戶去釋放 CarBulider::_car->setName("Ferrari"); cout << "原型設計完畢,準備進入下一階段" << endl;}void FerrariBulider::wheelInstall(int time){ cout << "初始化第" << time << "個輪子" << endl; cout << "組裝中" << endl; //實現代碼,比如輪子類 cout << "輪子組裝完畢,進入下一階段" << endl;}void FerrariBulider::smartInit(){ cout << "機動層初始化" << endl; cout << "機動層正常,進入下一階段" << endl;}void FerrariBulider::systemTest(){ cout << "汽車效能測試" << endl; cout << "安全性測試" << endl; cout << "試跑正常" << endl; cout << "構建成功" << endl;}
Diretor:
class Director{ public: Director(){ } Car* construct(CarBulider &);};Car* Director::construct(CarBulider &b){ //指標記憶體泄露問題,如果是這樣調用construct(new carbulider). b.designPrototype(); for (int i = 0; i < 4; i++) { b.wheelInstall(i); } b.smartInit(); b.systemTest(); return b.getResult();}
使用方式:
int main(){ FerrariBulider b; Director d; Car *f = d.construct(b); f->sayName(); return 0;}
結果:
細節問題好頭疼,c++實現方式很多,又要擔心記憶體泄露。所以把builder之間改成引用,由使用者覺決定。但是這個時候又設計到const的問題,如果用const那麼相應的函式宣告也應該改。
設計模式學習總結:(9)建造者模式