[作者:byeyear Email:byeyear@hotmail.com 首發:cnblogs 轉載請注明]
在本文的開頭,先森森的鄙視下自己……將Builder模式反反復復讀了七八遍,才敢說自己對其有了初步的了解。這比花在Abstract Factory上的時間長多了。如果GoF將Builder模式放在第一個講,估計我就會把這本書歸結成天書直接扔一邊了。
Builder模式的關鍵在於,將“要做什么”與“做出來”分離,將“如何裝配”與“完成裝配”分離:
Director知道“要做什么”, Builder負責“做出來”;
Director負責指揮, Builder負責實施;
Director負責讀懂建築圖紙,Builder負責澆鑄鋼筋水泥;
Director手里有裝配圖, Builder執行具體的裝配工作。
說得更加極端一點,只有Director才知道要做出來的是什么東西,但不具體動手;而Builder只負責根據Director的指揮去做事情,但它甚至不知道自己做出來的是什么——雖然最終產品是由Builder交付的。從這個角度來說,將Director翻譯成“指揮官”,builder翻譯成“執行者”似乎更妥帖。
用GoF的代碼來做例子:
Maze* MazeGame::CreateMaze(MazeBuilder& builder) { // director想要做個新迷宮 // 他們找了個施工隊builder // director說,先做個地基吧 // builder就做了個地基 builder.BuildMaze(); // director又讓builder做了兩個房間 builder.BuildRoom(1); builder.BuildRoom(2); // director跟builder說還要在兩個房間之間打個門洞 builder.BuildDoor(1, 2); // director說,把你做的東西交給我吧 return builder.GetMaze(); }
過年了,director和builder各自回家。親戚朋友聚會的時候說起這一年都干了些什么——
director說,我找施工隊造了個迷宮,這個迷宮有兩個房間和一個門(真夠寒酸……);
builder說,我接了個活,造了兩個房間,還在兩個房間之間打了個洞。天知道這玩意是干嘛用的,那個director准是腦袋秀逗了!
第二年,director准備繼續造迷宮,而builder繼續在市場上攬活。
director這次另外找了個施工隊,新的施工隊同樣會干打地基、造房子、打門洞這些活,但新施工隊造的房子是三角形的,而打出的門洞是半圓的:
{ // 造三角房間和圓門洞的builder AnotherMazeBuilder builder; // 開工吧,童鞋們! CreateMaze((MazeBuilder&)builder); }
而原來的builder們有了新的東家,新東家造的迷宮布局不太一樣,不過同樣是由房間和門洞組成:
{ builder.BuildMaze(); builder.BuildRoom(0); builder.BuildRoom(1); builder.BuildRoom(2); builder.BuildRoom(0,1); builder.BuildRoom(1,2); return Builder.GetMaze(); }
實際上,上面的例子還不是太完善。例如,我們可以將迷宮布局和該迷宮所用房間形狀放在文件里(同一個迷宮使用相同的房間形狀),而director負責解析文件結構並將任務派遣給builder們。這樣,不同的迷宮布局及它們所用房間形狀可以通過更換文件實現,而director不變。如果你需要六邊形的迷宮房間和三角形的門洞,只要重新實現一個新的builder,然后讓director將建造房間、門洞和組裝的任務派遣給這個新的builder。這樣的例子就更接近於GoF書中所用的RTFReader了。
這里順便引用下《大話設計模式》一書中的相應例子,那個例子中要求小人不能缺胳膊少腿,但從上文中我們可以看出,Builder模式其實是可以造出斷臂維納斯的:
CreateVenus(PersonBuilder& builder) { builder->Prepare(); builder->BuildHead(); builder->BuildBody(); // 斷臂的Venus // builder->BuildArmLeft(); // builder->BuildArmRight(); builder->BuildLegLeft(); builder->BuildLegRight(); return builder->GetPerson(); }
PersonBuilder類實際上並不知道自己build出來的是不是個完整的Person,只是根據Director的要求造出Head,body,……,並組裝起來。而造出的到底是人棍還是無頭騎士,這個是Director決定的。
[2014.08.01] 當我們創建對話框的時候,是否可考慮builder模式?Director知道對話框上有哪些子窗口,而Builder負責構建這些子窗口並layout之……