第二十三章 命令模式(烤羊肉串引来的思考)

  1. <?php
  2. //烤串
  3. class Barbecuer
  4. {
  5. public function bakeMutton()
  6. {
  7. echo "烤羊肉串\n";
  8. }
  9. public function bakeChickenWing()
  10. {
  11. echo "烤鸡翅\n";
  12. }
  13. }
  14. // 抽象命令
  15. abstract class Command
  16. {
  17. protected $receiver;
  18. function __construct(Barbecuer $receiver)
  19. {
  20. $this->receiver = $receiver;
  21. }
  22. abstract public function excuteCommand();
  23. }
  24. //烤羊肉
  25. class BakeMuttonCommand extends Command
  26. {
  27. public function excuteCommand()
  28. {
  29. $this->receiver->bakeMutton();
  30. }
  31. }
  32. //烤鸡翅
  33. class BakeChickenWingCommand extends Command
  34. {
  35. public function excuteCommand()
  36. {
  37. $this->receiver->bakeChickenWing();
  38. }
  39. }
  40. //服务员
  41. class Waiter
  42. {
  43. private $commands = [];
  44. //设置订单
  45. public function setOrder(Command $command)
  46. {
  47. if ($command instanceof BakeChickenWingCommand)
  48. {
  49. echo "服务员: 鸡翅没有了,请点别的烧烤\n";
  50. } else {
  51. echo "增加订单\n";
  52. array_push($this->commands, $command);
  53. }
  54. }
  55. //取消订单
  56. public function cancelOrder(Command $command){}
  57. //通知执行
  58. public function notify()
  59. {
  60. foreach ($this->commands as $value) {
  61. $value->excuteCommand();
  62. }
  63. }
  64. }
  65. //客户端代码
  66. //开店前准备
  67. $boy = new Barbecuer();
  68. $bakeMuttonCommand1 = new BakeMuttonCommand($boy);
  69. $bakeMuttonCommand2 = new BakeMuttonCommand($boy);
  70. $bakeChickenWingCommand1 = new BakeChickenWingCommand($boy);
  71. $girl = new Waiter();
  72. //开门营业
  73. $girl->setOrder($bakeMuttonCommand1);
  74. $girl->setOrder($bakeMuttonCommand2);
  75. $girl->setOrder($bakeChickenWingCommand1);
  76. $girl->notify();

总结:

命令模式,将 一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

对请求派对或记录请求日志,以及日志可撤销的操作。

优点:第一,能较容易地设计一个命令队列;第二,在需要的情况下,可以较容易地将命令记入日志;第三,允许请求的一方决定是否要否决请求;第四,可以容易地实现对请求的撤销和重做;第五,由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易;最重要的是该 模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开。

敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般酒不要急着去实现它,事实上,在需要的时候通过重构实现这个模式并不难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。