建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

意图

将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

主要解决

主要解决在软件系统中,有时候面临着”一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

何时使用

一些基本部件不会变,而其组合经常变化的时候。

如何解决

将变与不变分离开。

关键代码

建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。

应用实例

  1. 去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的”套餐”。
  2. JAVA 中的 StringBuilder。

优点

  1. 建造者独立,易扩展。
  2. 便于控制细节风险。

缺点

  1. 产品必须有共同点,范围有限制。
  2. 如内部变化复杂,会有很多的建造类。

使用场景

  1. 需要生成的对象具有复杂的内部结构。
  2. 需要生成的对象内部属性本身相互依赖。

注意事项

与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
image.png

  1. #include "pch.h"
  2. #include <iostream>
  3. #include <vector>
  4. // 包装接口
  5. class IPacking
  6. {
  7. public:
  8. virtual std::string Pack() = 0;
  9. };
  10. // 瓶装
  11. class Bottle : public IPacking
  12. {
  13. public:
  14. virtual std::string Pack()
  15. {
  16. return std::string("Bottle");
  17. }
  18. };
  19. // 袋装
  20. class Wrapper : public IPacking
  21. {
  22. public:
  23. virtual std::string Pack()
  24. {
  25. return std::string("Wrapper");
  26. }
  27. };
  28. // 物品接口
  29. class IItem
  30. {
  31. public:
  32. virtual std::string Name() = 0;
  33. virtual IPacking* Packing() = 0;
  34. virtual int Price() = 0;
  35. };
  36. // 汉堡接口
  37. class IBurger : public IItem
  38. {
  39. public:
  40. virtual IPacking* Packing()
  41. {
  42. return new Wrapper();
  43. }
  44. };
  45. // 鸡肉汉堡
  46. class ChickenBurger : public IBurger
  47. {
  48. public:
  49. virtual std::string Name()
  50. {
  51. return std::string("ChickenBurger");
  52. }
  53. virtual int Price()
  54. {
  55. return 50;
  56. }
  57. };
  58. // 素食汉堡
  59. class VegBurger : public IBurger
  60. {
  61. public:
  62. virtual std::string Name()
  63. {
  64. return std::string("VegBurger");
  65. }
  66. virtual int Price()
  67. {
  68. return 25;
  69. }
  70. };
  71. // 冷饮接口
  72. class IColdDrink :public IItem
  73. {
  74. public:
  75. virtual IPacking* Packing()
  76. {
  77. return new Bottle();
  78. }
  79. };
  80. // 百事可乐
  81. class Pepsi : public IColdDrink
  82. {
  83. public:
  84. virtual std::string Name()
  85. {
  86. return std::string("Pepsi");
  87. }
  88. virtual int Price()
  89. {
  90. return 15;
  91. }
  92. };
  93. // 可口可乐
  94. class Coke : public IColdDrink
  95. {
  96. public:
  97. virtual std::string Name()
  98. {
  99. return std::string("Coke");
  100. }
  101. virtual int Price()
  102. {
  103. return 10;
  104. }
  105. };
  106. // 一餐饭
  107. class Meal
  108. {
  109. public:
  110. // 添加物品
  111. void AddItem(IItem* pItem)
  112. {
  113. pItems.push_back(pItem);
  114. }
  115. // 获取总价
  116. float GetCost()
  117. {
  118. float cost = 0.0f;
  119. for (IItem* pItem : pItems)
  120. {
  121. cost += pItem->Price();
  122. }
  123. return cost;
  124. }
  125. // 显示物品
  126. void ShowItems()
  127. {
  128. for (IItem* pItem : pItems)
  129. {
  130. std::cout << "Item:" << pItem->Name().c_str() << " Price:" << pItem->Price()
  131. << " Packing:" << pItem->Packing()->Pack().c_str() << std::endl;
  132. }
  133. }
  134. ~Meal()
  135. {
  136. for (IItem* pItem : pItems)
  137. {
  138. delete(pItem);
  139. pItem = nullptr;
  140. }
  141. }
  142. private:
  143. std::vector<IItem*> pItems;
  144. };
  145. // 准备一餐饭
  146. class MealBuilder
  147. {
  148. public:
  149. // 准备素餐
  150. Meal* PrepareVegMeal()
  151. {
  152. Meal* pMeal = new Meal();
  153. IItem* pCoke = new Coke();
  154. IItem* pVegBurger = new VegBurger();
  155. pMeal->AddItem(pCoke);
  156. pMeal->AddItem(pVegBurger);
  157. return pMeal;
  158. }
  159. // 准备荤餐
  160. Meal* PrepareNonVegMeal()
  161. {
  162. Meal* pMeal = new Meal();
  163. IItem* pCoke = new Coke();
  164. IItem* pVegBurger = new VegBurger();
  165. pMeal->AddItem(pCoke);
  166. pMeal->AddItem(pVegBurger);
  167. return pMeal;
  168. }
  169. };
  170. // 调用示例
  171. int main()
  172. {
  173. MealBuilder mealBuilder;
  174. Meal* VegMeal = mealBuilder.PrepareNonVegMeal();
  175. std::cout << "Veg Meal:" << std::endl;
  176. VegMeal->ShowItems();
  177. std::cout << "Total Cost:" << VegMeal->GetCost() << std::endl;
  178. Meal* NonVegMeal = mealBuilder.PrepareNonVegMeal();
  179. std::cout << "Non Veg Meal:" << std::endl;
  180. NonVegMeal->ShowItems();
  181. std::cout << "Total Cost:" << NonVegMeal->GetCost() << std::endl;
  182. }
>>>
Veg Meal:
Item:Coke Price:10 Packing:Bottle
Item:VegBurger Price:25 Packing:Wrapper
Total Cost:35
Non Veg Meal:
Item:Coke Price:10 Packing:Bottle
Item:VegBurger Price:25 Packing:Wrapper
Total Cost:35