1. <?php
  2. /**
  3. * 设计模式之抽象工厂模式
  4. * 小黄牛
  5. */
  6. header("Content-type: text/html; charset=utf-8");
  7. /****************************** 产品 *********************************/
  8. # 接口 - 兵营
  9. interface Barracks{
  10. public function Make(); // 生产
  11. }
  12. # 接口 - 装备库
  13. interface Equipment{
  14. public function Make(); // 生产
  15. }
  16. /**************** 生产士兵 ******************/
  17. # 创建 - 步兵
  18. class Infantry implements Barracks{
  19. public function Make() { echo ',步兵防守! <br/>';}
  20. }
  21. # 创建 - 骑兵
  22. class Cavalry implements Barracks{
  23. public function Make() { echo ',骑兵冲锋! <br/>';}
  24. }
  25. /**************** 生产装备 ******************/
  26. # 创建 - 武器
  27. class Arms implements Equipment{
  28. public function Make() { echo '装备武器,攻击力+100 ';}
  29. }
  30. # 创建 - 盔甲
  31. class Nail implements Equipment{
  32. public function Make() { echo '装备盔甲,防御力+50 ';}
  33. }
  34. /****************************** 工厂 *********************************/
  35. # 接口 - 顶级抽象工厂
  36. interface TopFactory{
  37. public function Arms(); // 武器
  38. public function Nail(); // 盔甲
  39. public function Go($Barracks); // 士兵执行动作
  40. }
  41. # 具体化 - 工厂A - 该套餐只能装备武器
  42. class A implements TopFactory{
  43. public function Arms(){return new Arms();} // 只有武器
  44. public function Nail(){return null;} // 没有盔甲
  45. public function Go($Barracks){
  46. $A = $this->Arms();
  47. $N = $this->Nail();
  48. if($A){$A->Make();}
  49. if($N){$N->Make();}
  50. $Barracks->Make();
  51. }
  52. }
  53. # 具体化 - 工厂B - 该套餐只能装备盔甲
  54. class B implements TopFactory{
  55. public function Arms(){return null;} // 没有武器
  56. public function Nail(){return new Nail();} // 只有盔甲
  57. public function Go($Barracks){
  58. $A = $this->Arms();
  59. $N = $this->Nail();
  60. if($A){$A->Make();}
  61. if($N){$N->Make();}
  62. $Barracks->Make();
  63. }
  64. }
  65. # 具体化 - 工厂C - 该套餐什么装备都有,土豪必备
  66. class C implements TopFactory{
  67. public function Arms(){return new Arms();}// 有武器
  68. public function Nail(){return new Nail();} // 有盔甲
  69. public function Go($Barracks){
  70. $A = $this->Arms();
  71. $N = $this->Nail();
  72. if($A){$A->Make();}
  73. if($N){$N->Make();}
  74. $Barracks->Make();
  75. }
  76. }
  77. /****************************** 测试 *********************************/
  78. $A = new A(); // 套装-1
  79. $B = new B(); // 套装-2
  80. $C = new C(); // 套装-3
  81. $B->Go(new Infantry()); // 步兵使用套装-2
  82. $A->Go(new Cavalry()); // 骑兵使用套装-1
  83. $C->Go(new Cavalry()); // 骑兵使用套装-3

浏览器输出

  1. 装备盔甲,防御力+50 ,步兵防守!
  2. 装备武器,攻击力+100 ,骑兵冲锋!
  3. 装备武器,攻击力+100 装备盔甲,防御力+50 ,骑兵冲锋!

本案例设计原型

  1. 假设兵营里只能生产两种士兵。
  2. 步兵 骑兵
  3. | |
  4. 防守 冲锋
  5. 装备
  6. 武器 盔甲
  7. 武器与盔甲之间交由工厂去组合,再交由士兵穿戴,执行防守或冲锋动作。

应用场景

  1. 1、游戏开发中的多风格系列场景(套餐),比如道路(接口),房屋,管道等。
  2. 2、系统要在三个不同平台上运行,比如WindowsLinuxAndroid上运行,你会怎么设计?通过抽象工厂模式屏蔽掉操作系统对应用的影响。三个不同操作系统上的软件功能、应用逻辑、UI都应该是非常类似,唯一不同的是调用不同的工厂方法,由不同的产品类去处理与操作系统交互的信息。
  3. 3、需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。

三种工厂模式总结

  1. 1.三种在形式和特点上极为相似,最终目的都是解耦。将对象的创建过程进行封装,使客户端可以直接得到对象,而不用去关心如何创建对象。
  2. 2.对比
  3. 工厂方法模式:用于创建复杂对象。(单点食物)
  4. 抽象工厂模式:用于创建一组相关或相互依赖的复杂对象。(买套餐)
  5. 工厂方法创建一般只有一个方法,创建一种产品。抽象工厂一般有多个方法,创建一系列产品。

我们不必去在意模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了,而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。