剛開始我一直感覺建造者模式不太好懂,也許是我笨了點緣故,勤能補拙嘛,所以只能多看多想了
大話設計模式裡面那個對於建造者模式我講解,個人感覺不太好理解,我是看了很多遍也沒體會到那樣設計的精髓,後來在另一本設計模式上才稍微領悟到了點,
在這裡我想到一個比較形象的例子:
比如我某天去吃蘭州拉麵,他們有不同的套餐,套餐裡包含的種類是一樣的,都有一
碗拉麵,一份泡菜,一杯飲料。但是不同的套餐裡這3樣又都不是全部一樣的,也許分量和品質有差別。此時我們就可以用建造者模式。
這裡我沒有合適的UML圖,大致說一下模型:客戶根據套餐不同,跟收銀員點了一份A套餐的拉麵,另一名客戶同時又點了一份B套餐的拉麵,
這時收銀員把這兩個單子轉交給後台,其實也就是廚房,廚師看到這兩個單子的不同而煮不同的拉麵,然後返回給服務員,服務員分發拉麵給客戶!
1.建造者(B u i l d e r)角色:給出一個抽象介面,以規範產品對象的各個組成成分的建造。
2.具體建造者(Co n cre te B u i l d e r)角色:擔任這個角色的是於應用程式緊密相關的類,它們在應用程式調用下創
建產品執行個體。
3.指導者(D i re cto r)角色:擔任這個角色的類調用具體建造者角色以建立產品對象。是收銀員,他知道我想要什麼套餐,他會告訴裡面的
店員工去準備什麼套餐。
用代碼實現如下:
class Food //定義產品類,指示拉麵的一些屬性{private:vector<string> mFoodName;vector<int> mPrice;public:void add(string foodName,int price){mFoodName.push_back(foodName);mPrice.push_back(price);}void show(){cout<<"food list:"<<endl;cout<<"_______________________"<<endl;for(int i=0;i<mFoodName.size();++i){cout<<mFoodName[i]<<" "<<mPrice[i]<<endl;}}};class Builder //定義抽象的製作類,含有三個製作的環節和一個返回製作出來的產品方法{public:virtual void BuildCoolDish() = 0;virtual void BuildDrink() = 0;virtual void BuildRice() = 0;virtual Food* GetFood() = 0;};class BuilderA:public Builder //製作者A,我們假定他做出來的涼菜收20,飲料15,拉麵25,總共60元,也就是說收銀員接到60元的套餐就交給A來做{public:BuilderA(){food = new Food();}virtual void BuildCoolDish(){cout<<"涼菜已經製作好,已加入製作工序容器(其實也就是做好了一樣放在了盤子裡)"<<endl;food->add("CoolDish",20);}virtual void BuildDrink(){cout<<"飲料製作好了,已加入製作工序容器(放在了杯子裡)"<<endl;food->add("drink",15);}virtual void BuildRice(){cout<<"拉麵做好了,放棄製作工序容器(放在了盤子裡)"<<endl;food->add("Rice",25);}virtual Food* GetFood(){return food;}private:Food *food;};class BuilderB:public Builder //製作者B,我們假定他做出來的涼菜收30,飲料20,拉麵20,總共70元,也就是說收銀員接到70元的套餐就交給B來做{public:BuilderB(){food = new Food();}virtual void BuildCoolDish(){cout<<"涼菜已經製作好,已加入製作工序容器(其實也就是做好了一樣放在了盤子裡)"<<endl;food->add("CoolDish",30);}virtual void BuildDrink(){cout<<"飲料製作好了,已加入製作工序容器(放在了杯子裡)"<<endl;food->add("drink",20);}virtual void BuildRice(){cout<<"拉麵做好了,放棄製作工序容器(放在了盤子裡)"<<endl;food->add("Rice",20);}virtual Food* GetFood(){return food;}private:Food *food;};//定義收銀員class FoodManager{private:Builder *builder;public:FoodManager(){builder = NULL;};Food* FoodInfo(char ch){if(ch == 'A')builder = new BuilderA();else if(ch == 'B')builder = new BuilderB();else//你還可以加其他套餐;;builder->BuildCoolDish();builder->BuildDrink();builder->BuildRice();return builder->GetFood();}};int main(){FoodManager *p = new FoodManager();char ch;//客戶到來,輸入需要哪種套餐for(int i=0;i<5;i++){cin>>ch;p->FoodInfo(ch)->show();cout<<endl;}system("pause");return 0;}
這個例子在FoodManager的時候還利用了簡單原廠模式,其實更好的設計可以把FoodManager改寫成單例模式,因為一般一個收銀員在指示其他所有的工作者聽從她的指揮,好了,總結一下建造模式:
1、建造者模式的使用使得產品的內部表象可以獨立的變化。使用建造者模式可以使用戶端不必知道產品內部組成的
細節。
2、每一個B u i l d e r都相對獨立,而與其它的B u i l d e r無關。
3、可使對構造過程更加精細控制。
4、將構建代碼和實現代碼分開。
5、建造者模式的缺點在於難於應付“分步驟構建演算法”的需求變動
關於建造者模式的標準執行個體,相信學過C#的都知道有一個stringbuilder 他就是一個利用這種思想設計出來的,在我自己構思的C++庫中我也會用string實作一個stringbuilder出來,到飯點了,閃!