学习php设计模式 php实现命令模式(command)


Posted in PHP onDecember 08, 2015

一、意图
将一个请求封装为一个对象,从而使用你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。
可变的方面是:何时,怎样满足一个请求
命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。
请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
二、命令模式结构图

学习php设计模式 php实现命令模式(command) 

三、命令模式中主要角色
命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。
具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Execute()方法,负责调用接收考的相应操作。Execute()方法通常叫做执行方法。
客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。
请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。
接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
四、命令模式的优点
命令模式的优点:
1、命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分离开。
2、命令类与其他任何别的类一样,可以修改和推广。
3、可以把命令对象聚合在一起,合成为合成命令。
4、可以很容易的加入新的命令类。
命令模式的缺点:可能会导致某些系统有过多的具体命令类。
五、命令模式适用场景
1、抽象出待执行的动作以参数化对象。Command模式是回调机制的一个面向对象的替代品。
2、在不同的时刻指定、排列和执行请求。
3、支持取消操作。
4、支持修改日志。
5、用构建在原语操作上的高层操作构造一个系统。Command模式提供了对事务进行建模的方法。Command有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。
六、命令模式与其它模式
合成模式(composite模式):Composite模式可被实现宏命令
原型模式(prototype模式):如果命令类带有clone(或在之前的文章中提到的copy方法)方法,命令就可以被复制。在命令模式支持多次取消操作时可能需要用到此模式,以复制当前状态的Command对象
七、命令模式PHP示例

<?php
/**
 * 命令角色
 */
interface Command {
 
  /**
   * 执行方法
   */
  public function execute();
}
 
/**
 * 具体命令角色
 */
class ConcreteCommand implements Command {
 
  private $_receiver;
 
  public function __construct(Receiver $receiver) {
    $this->_receiver = $receiver;
  }
 
  /**
   * 执行方法
   */
  public function execute() {
    $this->_receiver->action();
  }
}
 
/**
 * 接收者角色
 */
class Receiver {
 
  /* 接收者名称 */
  private $_name;
 
  public function __construct($name) {
    $this->_name = $name;
  }
 
  /**
   * 行动方法
   */
  public function action() {
    echo $this->_name, ' do action.<br />';
  }
}
 
/**
 * 请求者角色
 */
class Invoker {
 
  private $_command;
 
  public function __construct(Command $command) {
    $this->_command = $command;
  }
 
  public function action() {
    $this->_command->execute();
  }
}
 
/**
 * 客户端
 */
class Client {
 
   /**
   * Main program.
   */
  public static function main() {
    $receiver = new Receiver('phpppan');
    $command = new ConcreteCommand($receiver);
    $invoker = new Invoker($command);
    $invoker->action();
  }
}
 
Client::main();
 
?>

八、命令模式协作
1、Client创建一个ConcreteCommand对象并指定它的Receiver对象
2、某Invoker对象存储该ConcreteCommand对象
3、该Invoker通过调用Command对象的execute操作来提交一个请求。若该命令是可撤消的,ConcreteCommand就在执行execute操作之前存储当前状态以用于取消命令。
4、ConcreteCommand对象对调用它的Receiver的一些操作以执行该请求。
九、宏命令
在这里,我们以一个简单的增加和粘贴功能为例,将这两个命令组成一个宏命令。
我们可以新建复制命令和粘贴命令,然后将其添加到宏命令中去。
如下所示代码:

<?php
/**
 * 命令角色
 */
interface Command {
 
  /**
   * 执行方法
   */
  public function execute();
}
 
/**
 * 宏命令接口
 */
interface MacroCommand extends Command {
 
  /**
   * 宏命令聚集的管理方法,可以删除一个成员命令
   * @param Command $command
   */
  public function remove(Command $command);
 
  /**
   * 宏命令聚集的管理方法,可以增加一个成员命令
   * @param Command $command
   */
  public function add(Command $command);
 
}
 
 
class DemoMacroCommand implements MacroCommand {
 
  private $_commandList;
 
  public function __construct() {
    $this->_commandList = array();
  }
 
  public function remove(Command $command) {
    $key = array_search($command, $this->_commandList);
    if ($key === FALSE) {
      return FALSE;
    }
 
    unset($this->_commandList[$key]);
    return TRUE;
  }
 
  public function add(Command $command) {
    return array_push($this->_commandList, $command);
  }
 
  public function execute() {
    foreach ($this->_commandList as $command) {
      $command->execute();
    }
 
  }
 
}
 
/**
 * 具体拷贝命令角色
 */
class CopyCommand implements Command {
 
  private $_receiver;
 
  public function __construct(Receiver $receiver) {
    $this->_receiver = $receiver;
  }
 
  /**
   * 执行方法
   */
  public function execute() {
    $this->_receiver->copy();
  }
}
 
/**
 * 具体拷贝命令角色
 */
class PasteCommand implements Command {
 
  private $_receiver;
 
  public function __construct(Receiver $receiver) {
    $this->_receiver = $receiver;
  }
 
  /**
   * 执行方法
   */
  public function execute() {
    $this->_receiver->paste();
  }
}
 
/**
 * 接收者角色
 */
class Receiver {
 
  /* 接收者名称 */
  private $_name;
 
  public function __construct($name) {
    $this->_name = $name;
  }
 
  /**
   * 复制方法
   */
  public function copy() {
    echo $this->_name, ' do copy action.<br />';
  }
 
  /**
   * 粘贴方法
   */
  public function paste() {
    echo $this->_name, ' do paste action.<br />';
  }
}
 
/**
 * 请求者角色
 */
class Invoker {
 
  private $_command;
 
  public function __construct(Command $command) {
    $this->_command = $command;
  }
 
  public function action() {
    $this->_command->execute();
  }
}
 
/**
 * 客户端
 */
class Client {
 
   /**
   * Main program.
   */
  public static function main() {
    $receiver = new Receiver('phpppan');
    $pasteCommand = new PasteCommand($receiver);
    $copyCommand = new CopyCommand($receiver);
 
    $macroCommand = new DemoMacroCommand();
    $macroCommand->add($copyCommand);
    $macroCommand->add($pasteCommand);
 
    $invoker = new Invoker($macroCommand);
    $invoker->action();
 
    $macroCommand->remove($copyCommand);
    $invoker = new Invoker($macroCommand);
    $invoker->action();
  }
}
 
Client::main();
 
 
?>

以上就是使用php实现命令模式的代码,还有一些关于命令模式的概念区分,希望对大家的学习有所帮助。

PHP 相关文章推荐
谈谈PHP语法(3)
Oct 09 PHP
如何在PHP中使用Oracle数据库(3)
Oct 09 PHP
图书管理程序(二)
Oct 09 PHP
php daodb插入、更新与删除数据
Mar 19 PHP
php根据身份证号码计算年龄的实例代码
Jan 18 PHP
PHP使用Session遇到的一个Permission denied Notice解决办法
Jul 30 PHP
php判断输入是否是纯数字,英文,汉字的方法
Mar 05 PHP
php判断数组中是否存在指定键(key)的方法
Mar 17 PHP
PHP实现全角字符转为半角方法汇总
Jul 09 PHP
PHP异常处理定义与使用方法分析
Jul 25 PHP
php基于session锁防止阻塞请求的方法分析
Aug 07 PHP
php 字符串中是否包含指定字符串的多种方法
Apr 12 PHP
学习php设计模式 php实现合成模式(composite)
Dec 08 #PHP
如何使用GDB调试PHP程序
Dec 08 #PHP
PHP MPDF中文乱码的解决方式
Dec 08 #PHP
PHP使用MPDF类生成PDF的方法
Dec 08 #PHP
学习php设计模式 php实现享元模式(flyweight)
Dec 07 #PHP
学习php设计模式 php实现策略模式(strategy)
Dec 07 #PHP
学习php设计模式 php实现状态模式
Dec 07 #PHP
You might like
php使用Session和文件统计在线人数
2015/07/04 PHP
php开发工具有哪五款
2015/11/09 PHP
thinkphp5 URL和路由的功能详解与实例
2017/12/26 PHP
PHP isset()及empty()用法区别详解
2020/08/29 PHP
phpstorm最新激活码分享亲测phpstorm2020.2.3版可用
2020/11/22 PHP
从jquery的过滤器.filter()方法想到的
2013/09/29 Javascript
JavaScript中使用typeof运算符需要注意的几个坑
2014/11/08 Javascript
流量统计器如何鉴别C#:WebBrowser中伪造referer
2015/01/07 Javascript
JavaScript 匿名函数和闭包介绍
2015/04/13 Javascript
JavaScript中Function函数与Object对象的关系
2015/12/17 Javascript
微信小程序slider组件使用详解
2018/01/31 Javascript
VUE-Table上绑定Input通过render实现双向绑定数据的示例
2018/08/27 Javascript
详解微信小程序-扫一扫 wx.scanCode() 扫码大变身
2019/04/30 Javascript
JavaScript中的ES6 Proxy的具体使用
2019/06/16 Javascript
解决layui弹框失效的问题
2019/09/09 Javascript
VSCode 配置uni-app的方法
2020/07/11 Javascript
[52:05]EG vs OG 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
python网络编程之读取网站根目录实例
2014/09/30 Python
使用Python内置的模块与函数进行不同进制的数的转换
2016/03/12 Python
在windows下Python打印彩色字体的方法
2018/05/15 Python
Python Logging 日志记录入门学习
2018/06/02 Python
PyQt4编程之让状态栏显示信息的方法
2019/06/18 Python
Pandas操作CSV文件的读写实现方法
2019/11/13 Python
Python如何使用Gitlab API实现批量的合并分支
2019/11/27 Python
Python MOCK SERVER moco模拟接口测试过程解析
2020/04/13 Python
Django静态文件加载失败解决方案
2020/08/26 Python
python excel和yaml文件的读取封装
2021/01/12 Python
super关键字的用法
2012/04/10 面试题
银行实习人员自我鉴定
2013/09/22 职场文书
合作意向书模板
2014/03/31 职场文书
《蝙蝠和雷达》教学反思
2014/04/23 职场文书
小学雷锋月活动总结
2014/07/03 职场文书
2014年人力资源部工作总结
2014/11/19 职场文书
Go语言-为什么返回值为接口类型,却返回结构体
2021/04/24 Golang
Java使用JMeter进行高并发测试
2021/11/23 Java/Android
openEuler 搭建java开发环境的详细过程
2022/06/10 Servers