若转载教程,请注明出自SW-X框架官方文档!

    1. <?php
    2. /**
    3. * 设计模式之命令模式
    4. * 模拟场景:
    5. * 1、在古代,皇帝是最喜欢下达命令的角色,并且皇宫重地,除了皇子与护卫之外,就不能有其他的男人,
    6. * 所以每次下达命令时,皇上不可能将所有部门重臣都召唤到跟前,这个时候就需要有一个能够传达命令的角色。
    7. * 2、在古代,这个传递命令的角色很出名,他就是太监,太监并没有任何权力,但当他拿到命令时,便可以调派命令所对应的部门角色。
    8. * 3、假设皇上想派兵攻打岛国,让厨房做个早点这个时候就需要2个部门角色了。
    9. * 4、并且太监是需要调派命令的权力,这时我们设计一个接口,用于把每个命令具体化,不然太监也不知道自己该去调派什么命令。
    10. * 小黄牛
    11. */
    12. header("Content-type: text/html; charset=utf-8");
    13. /**
    14. * 接口 命令类
    15. */
    16. interface Initiator{
    17. public function Command(); // 抽象出一个普通命令接口
    18. }
    19. /**
    20. * 写张圣旨 - 皇上要打鬼子了
    21. */
    22. class DaZhang implements Initiator{
    23. public function Command(){
    24. echo '快去给我削了那帮鬼子!<br/>';
    25. }
    26. }
    27. /**
    28. * 写张圣旨 - 皇上要吃饭
    29. */
    30. class ChiFan implements Initiator{
    31. public function Command(){
    32. echo '给朕准备两桌好菜!<br/>';
    33. }
    34. }
    35. /**
    36. * 抽象 部门类
    37. */
    38. abstract class Command{
    39. public $name; // 部门名称
    40. protected $Initiator; // 命令的实例
    41. public function execute(){} // 抽象一个方法,所有部门都必须实现,用于执行命名
    42. }
    43. /**
    44. * 创建 - 兵部
    45. */
    46. class BingBu extends Command{
    47. public function __construct($Initiator){
    48. $this->name = '兵部';
    49. $this->Initiator = $Initiator; // 接圣旨
    50. }
    51. public function execute(){
    52. $this->Initiator->Command();
    53. }
    54. }
    55. /**
    56. * 创建 - 御膳房
    57. */
    58. class ChuFang extends Command{
    59. public function __construct($Initiator){
    60. $this->name = '御膳房';
    61. $this->Initiator = $Initiator; // 接圣旨
    62. }
    63. public function execute(){
    64. $this->Initiator->Command();
    65. }
    66. }
    67. /**
    68. * 抽象 对接类
    69. */
    70. abstract class Pickup{
    71. public $name; // 对接人名称
    72. protected $Initiator; // 部门的实例,你得告诉对接人要去哪里,并且对接人不该拥有任何操作命令的权限,防止中途被修改
    73. public function run_errands(){} // 抽象一个方法,对接人需要使用这个方法去发送命令
    74. }
    75. /**
    76. * 创建一个对接人 - 太监小李子
    77. */
    78. class TaiJian extends Pickup{
    79. public function __construct($Command){
    80. $this->name = '东厂- 小李子';
    81. $this->Command = $Command; // 接到部门地址
    82. }
    83. # 去传递命令咯
    84. public function run_errands(){
    85. echo $this->name . ',奉天承运:';
    86. $this->Command->execute();
    87. echo $this->Command->name . ',领旨!<br/>';
    88. }
    89. }
    90. /**
    91. * 创建一个发起人 - 皇上
    92. */
    93. class HuangShang{
    94. public function Go(){
    95. # 让小李子去兵部
    96. $tj1 = new Taijian(new BingBu(new DaZhang()));
    97. $tj1->run_errands();
    98. # 让小李子去御膳房
    99. $tj2 = new Taijian(new Chufang(new ChiFan()));
    100. $tj2->run_errands();
    101. }
    102. }
    103. $res= new HuangShang();
    104. $res->Go();

    浏览器输出

    1. 东厂- 小李子,奉天承运:快去给我削了那帮鬼子!
    2. 兵部,领旨!
    3. 东厂- 小李子,奉天承运:给朕准备两桌好菜!
    4. 御膳房,领旨!

    命令模式

    1. 抽象命令(Initiator),定义命令的接口,声明执行的方法。
    2. 具体命令(XInitiator),将需要执行的命令实现化;
    3. 抽象接收者(Command),声明接受者自身,并接纳命令实例,并定义一个方法,使用部门都应该在执行命令后给予上级回复。
    4. 具体接收者(XCommand),将接收者具体化。
    5. 抽象持有者(Pickup),这个角色相当于跑腿,它持有命令的制定到达地点,但却不能持有该命令的实例,以防止持有者在中途将命令修改。
    6. 具体持有者(XPickup),将持有者具体化。
    7. 控制者(DIY):创建命令对象,并让持有者到达指定接受者处传达 命令。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

    使用场景

    1. 1.系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
    2. 2.系统需要在不同的时间指定请求、将请求排队和执行请求。
    3. 3.系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
    4. 4.系统需要将一组操作组合在一起,即支持宏命令。
    1. 优点
    1. 1.降低对象之间的耦合度。
    2. 2.新的命令可以很容易地加入到系统中。
    3. 3.可以比较容易地设计一个组合命令。
    4. 4.调用同一方法实现不同的功能

    缺点

    1. 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。