PHP命令Command模式用法实例分析


Posted in PHP onAugust 08, 2018

本文实例讲述了PHP命令Command模式用法。分享给大家供大家参考,具体如下:

命令Command模式是GOF23种模式中的一种,是一种行为模式。这种模式很难理解。《设计模式》一书中对它语焉不详。而网上的一些文章对其的解释也是错误的。实际上,命令模式并不是那么神秘。

命令模式的理解,关键有2点:

1. 使用接口。通常命令模式的接口中只有一个方法。 实现类的方法有不同的功能,覆盖接口中的方法。在面向对象编程中,大量使用if…else…,或者switch…case…这样的条件选择语句是“最差实践”。通常这类代码,意味着有重构的余地。命令模式就是干掉条件选择语句的利器。

首先提供一个接口:

public interface Command {
  public void execute();
}

然后提供这个接口的实现类。每一个实现类的方法就是if…else…的一个代码块中的代码。这样,调用方直接把一个具体类的实例传进来即可。如:

Public void test(Command para){
  Para.execute();
}

不需要再判断出现了哪种情况,应该执行哪一段代码。一切的问题都由调用方处理。

如果不使用命令模式,那么如果情况逐步增多,如,从原来的2种,增加到20种,那么方法中的判断就会从1次增加到19次。而使用命令模式,仅仅调用方需要从2个实现类增加到20个实现类即可。上面的test方法根本不需要做任何改变。

2. 主要的用途是,使用参数回调模式。

最主要使用命令模式的方式是使用参数回调模式。命令接口作为方法的参数传递进来。然后,在方法体内回调该接口。

当然,命令模式还可以使用其他方式来使用。不一定非用参数回调模式。

了解完这些之后,可以看一下下面的程序例子。

<?php
  /**
   * 命令模式
   *
   * 将一个请求封装为一个对象从而使你可用不同的请求对客户进行参数化,对请求排除或记录请求日志,以及支持可取消的操作
   */
  // 命令接口
  interface Command
  {
    public function execute();
  }
  class Invoker
  {
    private $_command = array();
    public function setCommand($command) {
      $this->_command[] = $command;
    }
    public function executeCommand()
    {
      foreach($this->_command as $command)
      {
        $command->execute();
      }
    }
    public function removeCommand($command)
    {
      $key = array_search($command, $this->_command);
      if($key !== false)
      {
        unset($this->_command[$key]);
      }
    }
  }
  // 命令接受者
  class Receiver
  {
    private $_name = null;
    public function __construct($name) {
      $this->_name = $name;
    }
    public function action()
    {
       echo $this->_name." 执行攻击命令(action)<br />";
    }
    public function action1()
    {
      echo $this->_name." 执行防御命令(action1)<br/>";
    }
  }
  // 具体的命令
  class ConcreteCommand implements Command
  {
    private $_receiver;
    public function __construct($receiver)
    {
      $this->_receiver = $receiver;
    }
    public function execute()
    {
      $this->_receiver->action();
    }
  }
  // 具体命令1
  class ConcreteCommand1 implements Command
  {
    private $_receiver;
    public function __construct($receiver)
    {
      $this->_receiver = $receiver;
    }
    public function execute()
    {
      $this->_receiver->action1();
    }
  }
  // 具体命令2
  class ConcreteCommand2 implements Command
  {
    private $_receiver;
    public function __construct($receiver)
    {
      $this->_receiver = $receiver;
    }
    public function execute()
    {
      $this->_receiver->action();
      $this->_receiver->action1();
    }
  }
  $objRecevier = new Receiver("小狗");
  $objRecevier1 = new Receiver("刺蛇");
  $objRecevier2 = new Receiver("雷兽");
  $objCommand = new ConcreteCommand($objRecevier);
  $objCommand1 = new ConcreteCommand1($objRecevier);
  $objCommand2 = new ConcreteCommand($objRecevier1);
  $objCommand3 = new ConcreteCommand1($objRecevier1);
  $objCommand4 = new ConcreteCommand2($objRecevier2); // 使用 Recevier的两个方法
  $objInvoker = new Invoker();
  $objInvoker->setCommand($objCommand);
  $objInvoker->setCommand($objCommand1);
  $objInvoker->executeCommand();
  $objInvoker->removeCommand($objCommand1);
  $objInvoker->executeCommand();
  $objInvoker->setCommand($objCommand2);
  $objInvoker->setCommand($objCommand3);
  $objInvoker->setCommand($objCommand4);
  $objInvoker->executeCommand();
?>

程序运行结果:

小狗 执行攻击命令(action)
小狗 执行防御命令(action1)
小狗 执行攻击命令(action)
小狗 执行攻击命令(action)
刺蛇 执行攻击命令(action)
刺蛇 执行防御命令(action1)
雷兽 执行攻击命令(action)
雷兽 执行防御命令(action1)

命令模式的核心思想是,带有某个方法的具体类的实例,作为接口传给使用方。对象的具体类型信息消失。在使用方代码中拿到这个接口后调用这个接口的方法。

具体的执行效果,取决的命令发起人提供的对象是哪一个实现类的。这给了命令发起人完全的控制能力,而使用方代码不关心具体的命令类和方法。同时也使条件判断语句成为多余。

简单吗?命令模式其实就是这么简单。

其实,GOF的23个设计模式中,好几个模式使用了相同的技巧来实现。GOF对模式的划分,是根据目的来的,而不是技巧来的。因此,Command模式和策略模式等其实使用的技法是一样的。 上回和一个同事聊技术。他的背景是Windows C++和Windows驱动开发。 他说,他不知道什么设计模式。他觉得最有用的就是回调函数。Command模式也是使用回调函数。java没有函数指针,java中一切都是类和类的实例。因此,就需要使用一个只有一个函数的接口,它的实例表示函数指针。其实是一回事。

设计模式是比较低层次的设计思想。在更高层次上,还有更加宏观的一些设计技巧。 Bob大叔的一本书不错,忘记名字了。 《Unix编程艺术》也不错,都是讲更高层次上的设计的。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
Win9x/ME下Apache+PHP安装配置
Oct 09 PHP
为PHP初学者的8点有效建议
Nov 20 PHP
具有时效性的php加密解密函数代码
Jun 19 PHP
php 邮件发送问题解决
Mar 22 PHP
在Yii框架中使用PHP模板引擎Twig的例子
Jun 13 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(九)
Jun 24 PHP
Linux系统中设置多版本PHP共存配合Nginx服务器使用
Dec 21 PHP
基于thinkPHP框架实现留言板的方法
Oct 17 PHP
浅谈php和js中json的编码和解码
Oct 24 PHP
详解thinkphp5+swoole实现异步邮件群发(SMTP方式)
Oct 13 PHP
在PHP中实现使用Guzzle执行POST和GET请求
Oct 15 PHP
PHP中类与对象功能、用法实例解读
Mar 27 PHP
PHP耦合设计模式实例分析
Aug 08 #PHP
thinkPHP框架整合tcpdf插件操作示例
Aug 07 #PHP
php实现往pdf中加数字签名操作示例【附源码下载】
Aug 07 #PHP
php使用环形链表解决约瑟夫问题完整示例
Aug 07 #PHP
postman的安装与使用方法(模拟Get和Post请求)
Aug 06 #PHP
PHP实现的解汉诺塔问题算法示例
Aug 06 #PHP
PHP实现普通hash分布式算法简单示例
Aug 06 #PHP
You might like
全国FM电台频率大全 - 7 吉林省
2020/03/11 无线电
PHP Parse Error: syntax error, unexpected $end 错误的解决办法
2012/06/05 PHP
PHP无限分类(树形类)
2013/09/28 PHP
PHP实现支持SSL连接的SMTP邮件发送类
2015/03/05 PHP
javascript一些不错的函数脚本代码
2008/09/10 Javascript
IE6图片加载的一个BUG解决方法
2010/07/13 Javascript
网页加载时页面显示进度条加载完成之后显示网页内容
2012/12/23 Javascript
jquery表格内容筛选实现思路及代码
2013/04/16 Javascript
鼠标划过实现延迟加载并隐藏层的js代码
2013/10/11 Javascript
浏览器兼容console对象的简要解决方案分享
2013/10/24 Javascript
jQuery控制iFrame(实例代码)
2013/11/19 Javascript
jQuery 删除或是清空某个HTML元素示例
2014/08/04 Javascript
jquery实现可旋转可拖拽的文字效果代码
2016/01/27 Javascript
JS全角与半角转化实例(分享)
2017/07/04 Javascript
webpack构建vue项目的详细教程(配置篇)
2017/07/17 Javascript
浅谈React和Redux的连接react-redux
2017/12/04 Javascript
JavaScript封闭函数及常用内置对象示例
2019/05/13 Javascript
如何编写一个 Webpack Loader的实现
2020/10/18 Javascript
[00:12]2018DOTA2亚洲邀请赛 sylar表现SOLO技艺
2018/04/06 DOTA
[54:24]Optic vs TNC 2018国际邀请赛小组赛BO2 第二场
2018/08/18 DOTA
Tornado Web服务器多进程启动的2个方法
2014/08/04 Python
Python爬取个人微信朋友信息操作示例
2018/08/03 Python
mac PyCharm添加Python解释器及添加package路径的方法
2018/10/29 Python
详解Python:面向对象编程
2019/04/10 Python
pytorch 自定义卷积核进行卷积操作方式
2019/12/30 Python
PyCharm无法识别PyQt5的2种解决方法,ModuleNotFoundError: No module named 'pyqt5'
2020/02/17 Python
Xadmin+rules实现多选行权限方式(级联效果)
2020/04/07 Python
Python虚拟环境venv用法详解
2020/05/25 Python
Python 字典中的所有方法及用法
2020/06/10 Python
Python3合并两个有序数组代码实例
2020/08/11 Python
全面介绍python中很常用的单元测试框架unitest
2020/12/14 Python
浅谈three.js中的needsUpdate的应用
2012/11/12 HTML / CSS
请编程遍历页面上所有 TextBox 控件并给它赋值为 string.Empty
2015/12/03 面试题
幼儿园中班下学期评语
2014/04/18 职场文书
党的群众路线教育实践活动个人整改方案
2014/10/25 职场文书
如何用JavaScript实现一个数组惰性求值库
2021/05/05 Javascript