• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    PHP设计模式之命令模式示例详解

    前言

    命令模式,也称为动作或者事务模式,很多教材会用饭馆来举例。作为顾客的我们是命令的下达者,服务员是这个命令的接收者,菜单是这个实际的命令,而厨师是这个命令的执行者。那么,这个模式解决了什么呢?当你要修改菜单的时候,只需要和服务员说就好了,她会转达给厨师,也就是说,我们实现了顾客和厨师的解耦。也就是调用者与实现者的解耦。当然,很多设计模式可以做到这一点,但是命令模式能够做到的是让一个命令接收者实现多个命令(服务员下单、拿酒水、上菜),或者把一条命令转达给多个实现者(热菜厨师、凉菜厨师、主食师傅)。这才是命令模式真正发挥的地方!!

    Gof类图及解释

    GoF定义:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作

    GoF类图

    代码实现

    class Invoker
    {
     public $command;
     
     public function __construct($command)
     {
      $this->command = $command;
     }
    
     public function exec()
     {
      $this->command->execute();
     }
    }
    
    

    首先我们定义一个命令的接收者,或者说是命令的请求者更恰当。类图中的英文定义这个单词是“祈求者”。也就是由它来发起和操作命令。

    abstract class Command
    {
     protected $receiver;
    
     public function __construct(Receiver $receiver)
     {
      $this->receiver = $receiver;
     }
    
     abstract public function execute();
    }
    
    class ConcreteCommand extends Command
    {
     public function execute()
     {
      $this->receiver->action();
     }
    }
    
    

    接下来是命令,也就是我们的“菜单”。这个命令的作用是为了定义真正的执行者是谁。

    class Receiver
    {
     public $name;
    
     public function __construct($name)
     {
      $this->name = $name;
     }
    
     public function action()
     {
      echo $this->name . '命令执行了!', PHP_EOL;
     }
    }
    
    

    接管者,也就是执行者,真正去执行命令的人。

    // 准备执行者
    $receiverA = new Receiver('A');
    
    // 准备命令
    $command = new ConcreteCommand($receiverA);
    
    // 请求者
    $invoker = new Invoker($command);
    $invoker->exec();
    
    

    客户端的调用,我们要联系好执行者也就是挑有好厨子的饭馆(Receiver),然后准备好命令也就是菜单(Command),最后交给服务员(Invoker)。

    其实这个饭店的例子已经非常清晰了,对于命令模式真是完美的解析

    那说好的可以下多份订单或者给多个厨师呢?别急,下面的代码帮助我们解决这个问题

    完整代码: https://github.com/zhangyue0503/designpatterns-php/blob/master/09.command/source/command.php

    ?php
    
    class Invoker
    {
     private $command = [];
    
     public function setCommand(Command $command)
     {
      $this->command[] = $command;
     }
    
     public function exec()
     {
      if(count($this->command) > 0){
       foreach ($this->command as $command) {
        $command->execute();
       }
      }
     }
    
     public function undo()
     {
      if(count($this->command) > 0){
       foreach ($this->command as $command) {
        $command->undo();
       }
      }
     }
    }
    
    abstract class Command
    {
     protected $receiver;
     protected $state;
     protected $name;
    
     public function __construct(Receiver $receiver, $name)
     {
      $this->receiver = $receiver;
      $this->name = $name;
     }
    
     abstract public function execute();
    }
    
    class ConcreteCommand extends Command
    {
     public function execute()
     {
      if (!$this->state || $this->state == 2) {
       $this->receiver->action();
       $this->state = 1;
      } else {
       echo $this->name . '命令正在执行,无法再次执行了!', PHP_EOL;
      }
    
     }
     
     public function undo()
     {
      if ($this->state == 1) {
       $this->receiver->undo();
       $this->state = 2;
      } else {
       echo $this->name . '命令未执行,无法撤销了!', PHP_EOL;
      }
     }
    }
    
    class Receiver
    {
     public $name;
     public function __construct($name)
     {
      $this->name = $name;
     }
     public function action()
     {
      echo $this->name . '命令执行了!', PHP_EOL;
     }
     public function undo()
     {
      echo $this->name . '命令撤销了!', PHP_EOL;
     }
    }
    
    // 准备执行者
    $receiverA = new Receiver('A');
    $receiverB = new Receiver('B');
    $receiverC = new Receiver('C');
    
    // 准备命令
    $commandOne = new ConcreteCommand($receiverA, 'A');
    $commandTwo = new ConcreteCommand($receiverA, 'B');
    $commandThree = new ConcreteCommand($receiverA, 'C');
    
    // 请求者
    $invoker = new Invoker();
    $invoker->setCommand($commandOne);
    $invoker->setCommand($commandTwo);
    $invoker->setCommand($commandThree);
    $invoker->exec();
    $invoker->undo();
    
    // 新加一个单独的执行者,只执行一个命令
    $invokerA = new Invoker();
    $invokerA->setCommand($commandOne);
    $invokerA->exec();
    
    // 命令A已经执行了,再次执行全部的命令执行者,A命令的state判断无法生效
    $invoker->exec();
    
    

    我们的手机工厂和餐厅其实并没有什么两样,当我们需要代工厂来制作手机时,也是先下订单,这个订单就可以看做是命令。在这个订单中,我们会规定好需要用到的配件,什么型号的CPU,什么型号的内存,预装什么系统之类的。然后代工厂的工人们就会根据这个订单来进行生产。在这个过程中,我不用关心是某一个工人还是一群工人来执行这个订单,我只需要将这个订单交给和我们对接的人就可以了,然后只管等着手机生产出来进行验收咯!!

    完整代码: https://github.com/zhangyue0503/designpatterns-php/blob/master/09.command/source/command-up.php

    实例

    短信功能又回来了,我们发现除了工厂模式外,命令模式貌似也是一种不错的实现方式哦。在这里,我们依然是使用那几个短信和推送的接口,话不多说,我们用命令模式再来实现一个吧。当然,有兴趣的朋友可以接着实现我们的短信撤回功能哈,想想上面的命令取消是怎么实现的。

    短信发送类图

    完整源码: https://github.com/zhangyue0503/designpatterns-php/blob/master/09.command/source/command-message.php

    ?php
    
    class SendMsg
    {
     private $command = [];
    
     public function setCommand(Command $command)
     {
      $this->command[] = $command;
     }
     
     public function send($msg)
     {
      foreach ($this->command as $command) {
       $command->execute($msg);
      }
     }
    }
    
    abstract class Command
    {
     protected $receiver = [];
    
     public function setReceiver($receiver)
     {
      $this->receiver[] = $receiver;
     }
    
     abstract public function execute($msg);
    }
    
    class SendAliYun extends Command
    {
     public function execute($msg)
     {
      foreach ($this->receiver as $receiver) {
       $receiver->action($msg);
      }
     }
    }
    
    class SendJiGuang extends Command
    {
     public function execute($msg)
     {
      foreach ($this->receiver as $receiver) {
       $receiver->action($msg);
      }
     }
    }
    
    class SendAliYunMsg
    {
     public function action($msg)
     {
      echo '【阿X云短信】发送:' . $msg, PHP_EOL;
     }
    }
    
    class SendAliYunPush
    {
     public function action($msg)
     {
      echo '【阿X云推送】发送:' . $msg, PHP_EOL;
     }
    }
    
    class SendJiGuangMsg
    {
     public function action($msg)
     {
      echo '【极X短信】发送:' . $msg, PHP_EOL;
     }
    }
    
    class SendJiGuangPush
    {
     public function action($msg)
     {
      echo '【极X推送】发送:' . $msg, PHP_EOL;
     }
    }
    
    $aliMsg = new SendAliYunMsg();
    $aliPush = new SendAliYunPush();
    $jgMsg = new SendJiGuangMsg();
    $jgPush = new SendJiGuangPush();
    
    $sendAliYun = new SendAliYun();
    $sendAliYun->setReceiver($aliMsg);
    $sendAliYun->setReceiver($aliPush);
    
    $sendJiGuang = new SendJiGuang();
    $sendAliYun->setReceiver($jgMsg);
    $sendAliYun->setReceiver($jgPush);
    
    $sendMsg = new SendMsg();
    $sendMsg->setCommand($sendAliYun);
    $sendMsg->setCommand($sendJiGuang);
    
    $sendMsg->send('这次要搞个大活动,快来注册吧!!');
    
    

    说明

    到此这篇关于PHP设计模式之命令模式的文章就介绍到这了,更多相关PHP设计模式之命令模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • PHP设计模式(观察者模式)
    • 浅谈PHP设计模式之门面模式Facade
    • 浅谈PHP设计模式之对象池模式Pool
    • 详解PHP设计模式之依赖注入模式
    • PHP设计模式之迭代器模式的使用
    • 详解PHP八大设计模式
    • PHP设计模式之原型模式示例详解
    • PHP八大设计模式案例详解
    上一篇:如何重写Laravel异常处理类详解
    下一篇:PHP变量的作用范围实例讲解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    PHP设计模式之命令模式示例详解 PHP,设计模式,之,命令,模式,