设计模式之Builder模式 (C++实现)

来源:互联网 发布:ozzy osbourne 知乎 编辑:程序博客网 时间:2024/05/21 03:54

刚开始我一直感觉建造者模式不太好懂,也许是我笨了点缘故,勤能补拙嘛,所以只能多看多想了

大话设计模式里面那个对于建造者模式我讲解,个人感觉不太好理解,我是看了很多遍也没体会到那样设计的精髓,后来在另一本设计模式上才稍微领悟到了点,

 

在这里我想到一个比较形象的例子:

比如我某天去吃兰州拉面,他们有不同的套餐,套餐里包含的种类是一样的,都有一
碗拉面,一份泡菜,一杯饮料。但是不同的套餐里这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)角色:担任这个角色的类调用具体建造者角色以创建产品对象。是收银员,他知道我想要什么套餐,他会告诉里面的
店员工去准备什么套餐。

用代码实现如下:

[cpp] view plaincopyprint?
  1. class Food     //定义产品类,指示拉面的一些属性  
  2. {  
  3. private:  
  4.     vector<string> mFoodName;  
  5.     vector<int> mPrice;  
  6. public:  
  7.     void add(string foodName,int price)  
  8.     {  
  9.         mFoodName.push_back(foodName);  
  10.         mPrice.push_back(price);  
  11.     }  
  12.   
  13.     void show()  
  14.     {  
  15.         cout<<"food list:"<<endl;  
  16.         cout<<"_______________________"<<endl;  
  17.         for(int i=0;i<mFoodName.size();++i)  
  18.         {  
  19.             cout<<mFoodName[i]<<"  "<<mPrice[i]<<endl;  
  20.         }  
  21.     }  
  22.   
  23. };  
  24.   
  25. class Builder  //定义抽象的制作类,含有三个制作的环节和一个返回制作出来的产品方法  
  26. {  
  27. public:  
  28.     virtual void BuildCoolDish() = 0;  
  29.     virtual void BuildDrink() = 0;  
  30.     virtual void BuildRice() = 0;  
  31.     virtual Food* GetFood() = 0;  
  32. };  
  33.   
  34.   
  35. class BuilderA:public Builder  //制作者A,我们假定他做出来的凉菜收20,饮料15,拉面25,总共60元,也就是说收银员接到60元的套餐就交给A来做  
  36. {  
  37. public:  
  38.     BuilderA()  
  39.     {  
  40.         food = new Food();  
  41.     }  
  42.     virtual void BuildCoolDish()  
  43.     {  
  44.         cout<<"凉菜已经制作好,已加入制作工序容器(其实也就是做好了一样放在了盘子里)"<<endl;  
  45.         food->add("CoolDish",20);  
  46.     }  
  47.   
  48.     virtual void BuildDrink()  
  49.     {  
  50.         cout<<"饮料制作好了,已加入制作工序容器(放在了杯子里)"<<endl;  
  51.         food->add("drink",15);  
  52.     }  
  53.   
  54.     virtual void BuildRice()  
  55.     {  
  56.         cout<<"拉面做好了,放弃制作工序容器(放在了盘子里)"<<endl;  
  57.         food->add("Rice",25);  
  58.     }  
  59.   
  60.     virtual Food* GetFood()  
  61.     {  
  62.         return food;  
  63.     }  
  64. private:  
  65.     Food *food;  
  66. };  
  67.   
  68. class BuilderB:public Builder  //制作者B,我们假定他做出来的凉菜收30,饮料20,拉面20,总共70元,也就是说收银员接到70元的套餐就交给B来做  
  69. {  
  70. public:  
  71.     BuilderB()  
  72.     {  
  73.         food = new Food();  
  74.     }  
  75.     virtual void BuildCoolDish()  
  76.     {  
  77.         cout<<"凉菜已经制作好,已加入制作工序容器(其实也就是做好了一样放在了盘子里)"<<endl;  
  78.         food->add("CoolDish",30);  
  79.     }  
  80.   
  81.     virtual void BuildDrink()  
  82.     {  
  83.         cout<<"饮料制作好了,已加入制作工序容器(放在了杯子里)"<<endl;  
  84.         food->add("drink",20);  
  85.     }  
  86.   
  87.     virtual void BuildRice()  
  88.     {  
  89.         cout<<"拉面做好了,放弃制作工序容器(放在了盘子里)"<<endl;  
  90.         food->add("Rice",20);  
  91.     }  
  92.   
  93.     virtual Food* GetFood()  
  94.     {  
  95.         return food;  
  96.     }  
  97. private:  
  98.     Food *food;  
  99. };  
  100.   
  101. //定义收银员  
  102. class FoodManager  
  103. {  
  104. private:  
  105.     Builder *builder;  
  106. public:  
  107.     FoodManager(){builder = NULL;};  
  108.   
  109.     Food* FoodInfo(char ch)  
  110.     {  
  111.         if(ch == 'A')  
  112.             builder = new BuilderA();  
  113.         else if(ch == 'B')  
  114.             builder = new BuilderB();  
  115.         else  
  116.             //你还可以加其他套餐;  
  117.             ;  
  118.         builder->BuildCoolDish();  
  119.         builder->BuildDrink();  
  120.         builder->BuildRice();  
  121.   
  122.         return builder->GetFood();  
  123.     }  
  124.   
  125. };  
  126.   
  127. int main()  
  128. {  
  129.     FoodManager *p = new FoodManager();  
  130.     char ch;  
  131.     //客户到来,输入需要哪种套餐  
  132.     for(int i=0;i<5;i++)  
  133.     {  
  134.         cin>>ch;  
  135.         p->FoodInfo(ch)->show();  
  136.         cout<<endl;  
  137.     }  
  138.     system("pause");  
  139.     return 0;  
  140. }  


这个例子在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出来,到饭点了,闪!

原创粉丝点击