Php设计模式之【命令模式Command Pattern】
来源:互联网 发布:上海灵信官网软件下载 编辑:程序博客网 时间:2024/05/28 17:08
【案例】
黑枣玩具公司专门生产玩具,生产的玩具不限于狗、猫、狮子等四肢动物。每个玩具身上有两个按钮,分别支持两个操作——“张嘴”与“闭嘴”。
<代码实现>
<?php/** * 所有玩具需要实现的动作接口 */interface Toy{ /** * 玩具张嘴动作 * @abstract * @return mixed */ public function openMouth(); /** * 玩具闭嘴动作 * @abstract * @return mixed */ public function closeMouth();}/** * 所有玩具上的按钮被按下后需要实现的动作接口 */interface Ctrl{ /** * 按钮1被按下 * @abstract * @return mixed */ public function Bt1Pressed(); /** * 按钮2被按下 * @abstract * @return mixed */ public function Bt2Pressed();}/** *狗类玩具 */class Dog implements Toy,Ctrl{ public function openMouth() { echo "Dog Open Mouth\n"; } public function closeMouth() { echo "Dog Close Mouth\n"; } public function Bt1Pressed() { $this->openMouth(); } public function Bt2Pressed() { $this->closeMouth(); }}class testDriver{ public function run() { //新建一个狗玩具 $toy = new Dog(); //狗玩具按钮1被按下 $toy->Bt1Pressed(); //狗玩具按钮2被按下 $toy->Bt2Pressed(); }}$test = new testDriver();$test->run();<输出>
【系统要升级】
遥控科技发展,在玩具上的两个控制按钮就不再要了。黑枣玩具公司想要实现手机遥控玩具,
1. 通过设置手机,手机可以与不同玩具连接实现控制
2. 手机星号(*)按钮按键为“张嘴”控制按键
3. 手机井号(#)按钮按键为“闭嘴”控制按键
【分析OOA】
相对于旧版玩具,新的玩具需要实现玩具实体与控制体分离,即玩具狗身上不再有按钮,按钮要分离出来。也其实也是典型的命令模式场景。我们结合一个命令模式分析本案例。
【设计OOD】
<UML>
【说明】
命令模式是有5个角色来组成,分别为
1. 命令角色(Command):声明执行操作的接口。通常代码中表现为接口或者抽象类
在本例中可为玩具命令Command接口
2. 具体命令角色(Concrete Command):将一个接收者对象绑定于一个动作;调用接收者相应的操作,以实现命令角色声明的执行操作的接口。
在本例中为DogOpenMouthCommand、DogCloseMouthCommand、CatOpenMouthCommand、CatCloseMouthCommand的实例对象。
3. 请求者角色(Invoker):谁去调用命令对象执行这个请求。
谁来让狗猫张嘴闭嘴?当然是手机了。
4. 接收者角色(Receiver):知道如何实施与执行一个请求相关的操作。
在这里接收者为狗或者猫,即Receiver类的一个实例。Receiver们都实现了openMouth张嘴、closeMouth闭嘴操作。
5. 客户角色(Client):创建一个具体命令对象(并可以设定它的接收者)。
这里是手机玩家,即Client类的一个实例。
【编程 OOP:
<代码>
1. 先来看看命令接口的定义,示例代码如下:
/** * 命令接口 */interface Command{ /** * 执行命令对应的操作 */ public function execute();}
2. 再来看看具体的命令实现对象,示例代码如下:
/** * 具体的命令实现对象,示例代码如下: */class OpenMouthCommand implements Command{ /** * 持有相应的接收者对象 */ private $receiver; /** * 示意,命令对象可以有自己的状态 */ private $mouthstate = 0; /** * 构造方法,传入相应的接收者对象 * @param receiver 相应的接收者对象 */ public function __construct(Receiver $receiver) { $this->receiver = $receiver; } public function execute() { //通常会转调接收者对象的相应方法,让接收者来真正执行功能 $this->receiver->openMouth(); }}class CloseMouthCommand implements Command{ private $receiver; private $mouthstate = 0; public function __construct(Receiver $receiver) { $this->receiver = $receiver; } public function execute() { $this->receiver->closeMouth(); }}
3. 再来看看接收者对象的实现示意,示例代码如下:
/** * 接收者对象超类 */abstract class Receiver{ /** * 示意方法1,真正执行命令相应的操作 * 在本案例中实现张嘴操作 */ abstract function openMouth(); /** * 示意方法2,真正执行命令相应的操作 * 在本案例中实现闭嘴操作 */ abstract function closeMouth();}/** * 接收者对象:狗 */class DogReceiver extends Receiver{ public function openMouth() { echo "Dog open Mouth\n"; } public function closeMouth() { echo "Dog close Mouth\n"; }}/** * 接收者对象:猫 */class CatReceiver extends Receiver{ public function openMouth() { echo "Cat open Mouth\n"; } public function closeMouth() { echo "Cat close Mouth\n"; }}
4. 接下来看看Invoker对象,示例代码如下:
/** * 调用者 */class PhoneInvoker{ /** * 持有命令对象 */ private $_OpenMouthCommand = null; private $_CloseMouthComand = null; /** * 设置调用者持有的命令对象 * @param command 命令对象 */ public function setCommand($opencommand, $closecommand) { $this->_OpenMouthCommand = $opencommand; $this->_CloseMouthComand = $closecommand; } /** * 示意方法,要求命令执行请求 */ public function runBtStarPressed() { $this->_OpenMouthCommand->execute(); } public function runBtHashPressed() { $this->_CloseMouthComand->execute(); }}
5. 再来看看Client的实现,注意这个不是我们通常意义上的测试客户端,主要功能是要创建命令对象并设定它的接收者,因此这里并没有调用执行的代码,示例代码如下:
class Client{ protected $receiver; protected $invoker; //把手机跟玩具连接起来 public function linkToyAndPhone($receiver, $invoker) { $this->receiver = $receiver; $this->invoker = $invoker; $command1 = new OpenMouthCommand($this->receiver); $command2 = new CloseMouthCommand($this->receiver); //创建Invoker,把命令对象设置进去 $this->invoker->setCommand($command1, $command2); } //按下手机*键 public function pressBtStar() { $this->invoker->runBtStarPressed(); } //按下手机#键 public function pressBtHash() { $this->invoker->runBtHashPressed(); }}
【测试用例Test Case】
<代码>
class testDriver{ public function run() { //新建一个玩家 $client = new Client(); //新建一个狗玩具 $dog = new DogReceiver(); //新建一个猫玩具 $cat = new CatReceiver(); //新建一部手机控制端 $invoker = new PhoneInvoker(); //玩家把手机连上狗玩具 $client->linkToyAndPhone($dog, $invoker); //按下手机*键 $client->pressBtHash(); //按下手机#键 $client->pressBtStar(); //玩家把手机连上猫玩具 $client->linkToyAndPhone($cat, $invoker); //按下手机#键 $client->pressBtHash(); //按下手机*键 $client->pressBtStar(); }}$test = new testDriver();$test->run();
【输出】
【小结】
命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。而在上面的举例中并没有体现出来。其实命令模式之所以能够支持这种操作,完全得益于在请求者与接收者之间添加了中间角色。
为了实现undo功能,首先需要一个历史列表来保存已经执行过的具体命令角色对象;修改具体命令角色中的执行方法,使它记录更多的执行细节,并将自己放入历史列表中;并在具体命令角色中添加undo方法,此方法根据记录的执行细节来复原状态(很明显,首先程序员要清楚怎么来实现,因为它和execute的效果是一样的)。
命令模式还有一个常见的用法就是执行事务操作。这就是为什么命令模式还叫做事务模式的原因吧。它可以在请求被传递到接收者角色之前,检验请求的正确性,甚至可以检查和数据库中数据的一致性,而且可以结合组合模式的结构,来一次执行多个命令。
使用命令模式不仅仅可以解除请求者和接收者之间的耦合,而且可以用来做批处理操作,这完全可以发挥你自己的想象——请求者发出的请求到达命令角色这里以后,先保存在一个列表中而不执行;等到一定的业务需要时,命令模式再将列表中全部的操作逐一执行。
********************************************
* 作者:叶文涛
* 标题:Php设计模式之【命令模式Command Pattern】
* 参考:
*《设计模式:可复用面向对象软件基础 》(美)Erich Gamma 等著
*《Head First设计模式》Eric Freeman等著
*《PHP设计模式》Aaron Saray等著,梁志敏等译(PS:翻译的是狗屁水平)
******************转载请注明网址来源 ***************
- Php设计模式之【命令模式Command Pattern】
- 设计模式之命令模式(Command Pattern)
- 设计模式之命令模式(Command Pattern)
- 设计模式之命令模式---Command Pattern
- 命令设计模式(Command Pattern)
- 设计模式读书笔记之命令模式(Command Pattern)
- 设计模式笔记之命令模式(command Pattern)
- 设计模式之七 命令模式(Command Pattern)
- 设计模式之七:命令模式(Command Pattern)
- 设计模式之-命令模式(Command Pattern)
- JAVA设计模式之 命令模式【Command Pattern】
- 设计模式(行为型)之命令模式(Command Pattern)
- 设计模式之:命令模式(Command Pattern)
- 设计模式读书笔记之命令模式(Command Pattern)
- 设计模式总结之Command Pattern(命令模式)
- Net设计模式实例之命令模式(Command Pattern)
- 设计模式拾荒之命令模式( Command Pattern )
- 设计模式 - Command Pattern(命令模式)
- 数据挖掘--数据集
- sort排序(以ASCII码顺序输出列表)
- IIS,SQL2005,VS2008安装先后
- 一日一点RakNet(57)--EmailSender(邮件发送器)
- Mansory 算法分析
- Php设计模式之【命令模式Command Pattern】
- 友盟统计在我们游戏中的使用
- 如何用HTML5制作iPhone App
- .PHP $_SERVER返回上一页
- 分页类改进
- perl,python和ruby的对比
- erp书籍
- 分享一个HTML5的drag and drop API实现的图片拖拽分组效果
- Spring原理