php设计模式入门-命令模式
来源:互联网 发布:win10很卡怎么优化 编辑:程序博客网 时间:2024/05/21 07:02
场景:某家公司需要生产一款遥控器,可以控制家用电器的开关,该开关拥有五列两排按键,现在需要我们为这个遥控器编写程序来实现相应功能。
解决方案1:看到这样的需求场景,我们第一个想法可能是模拟js的onclick事件,每个按钮按下时触发事件,js调用后台程序执行相应逻辑。
弊端:这样的做法其实是一种硬编码。即各按键一次绑定永不能修改,在这个以人为本尊重用户体验的大环境下这十分的不人性化。
接下我们来看看命令模式怎样为我们解决这个难题:
命令模式的uml类图如下所示:
初看这幅uml图,其实我也觉得乱也没看懂,不过没关系,我们用代码来说明,先看第一个初始版本的设计:
command接口:Command.php
<?phpinterface Command{ public function execute();}
电灯类:Light.php
<?phpclass Light{ public function on(){ echo "the light is on <br/>"; } public function off(){ echo "the light is off <br/>"; }}
开灯命令类:LightOffCommand.php
<?phprequire_once 'Command.php';class LightOffCommand implements Command{ private $_light; public function __construct(Light $light){ $this->_light = $light; }/* (non-PHPdoc) * @see Command::execute() */ public function execute() { // TODO Auto-generated method stub $this->_light->off(); }}
关灯命令类:LightOnCommand.php
<?phprequire_once 'Command.php';class LightOnCommand implements Command{ private $_light; public function __construct(Light $light){ $this->_light = $light; }/* (non-PHPdoc) * @see Command::execute() */ public function execute() { // TODO Auto-generated method stub $this->_light->on(); }}
遥控器类:RemoteController.php
<?phpclass RemoteController{ private $_command; public function setCommand(Command $command){ $this->_command = $command; } public function bottonWasPressed(){ $this->_command->execute(); }}
入口文件:index.php
<?php//初尝命令模式require_once 'Light.php';require_once 'LightOffCommand.php';require_once 'LightOnCommand.php';require_once 'RemoteController.php';$light = new Light();$lightOnCommand = new LightOnCommand($light);$lightOffCommand = new LightOffCommand($light);$remoteController = new RemoteController();$remoteController->setCommand($lightOnCommand);$remoteController->bottonWasPressed();$remoteController->setCommand($lightOffCommand);$remoteController->bottonWasPressed();
可以看出比起硬编码,使用命令模式实现该需求具有更强的灵活性和可变性。
现在我们根据以上的代码再来解释一下上面的uml类图:
Command:声明执行操作的接口。调用接收者相应的操作,以实现执行的方法Execute,对应示例代码中的command.php。
ConcreteCommand:创建一个具体命令对象并设定它的接收者。通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。对应示例代码中的LightOffCommand.php和LightOnCommand.php
Invoker:要求该命令执行这个请求。通常会持有命令对象,可以持有很多的命令对象。对应示例代码中的RemoteController.php
Receiver:知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者,只要它能够实现命令要求实现的相应功能。 对应示例代码中的Light.php
Client:创建具体的命令对象,并且设置命令对象的接收者。真正使用命令的客户端是从Invoker来触发执行。 对应示例代码中的index.php
假设有了新的需求,遥控器需要拥有撤销功能,其实很简单,我们只需要在每一个ConcreteCommand类中加上一个undo方法就行,我们现在就来实现这个功能,代码如下:
命令接口:Command.php
<?phpinterface Command{ public function execute();}
关灯命令类:LightOffCommand.php
<?phprequire_once 'Command.php';class LightOffCommand implements Command{ private $_light; public function __construct(Light $light){ $this->_light = $light; }/* (non-PHPdoc) * @see Command::execute() */ public function execute() { // TODO Auto-generated method stub $this->_light->off(); } public function undo() { // TODO Auto-generated method stub $this->_light->on(); }}
开灯命令类:LightOnCommand.php
<?phprequire_once 'Command.php';class LightOnCommand implements Command{ private $_light; public function __construct(Light $light){ $this->_light = $light; }/* (non-PHPdoc) * @see Command::execute() */ public function execute() { // TODO Auto-generated method stub $this->_light->on(); } public function undo() { // TODO Auto-generated method stub $this->_light->off(); }}
电灯类:Light.php
<?phpclass Light{ public function on(){ echo "the light is on <br/>"; } public function off(){ echo "the light is off <br/>"; }}
关闭电风扇命令:CellingFanDownCommand.php
<?phprequire_once 'Command.php';class CellingFanDownCommand implements Command{ private $_celling_fan; public function __construct(CellingFan $cellingFan){ $this->_celling_fan = $cellingFan; }/* (non-PHPdoc) * @see Command::execute() */ public function execute() { // TODO Auto-generated method stub $this->_celling_fan->down(); } public function undo() { // TODO Auto-generated method stub $this->_celling_fan->up(); }}
开启电风扇命令:CellingFanUpCommand.php
<?phprequire_once 'Command.php';class CellingFanUpCommand implements Command{ private $_celling_fan; public function __construct(CellingFan $cellingFan){ $this->_celling_fan = $cellingFan; }/* (non-PHPdoc) * @see Command::execute() */ public function execute() { // TODO Auto-generated method stub $this->_celling_fan->up(); } public function undo() { // TODO Auto-generated method stub $this->_celling_fan->down(); }}
<?phpclass CellingFan{ public function up(){ echo "the cellingfan is up <br/>"; } public function down(){ echo "the cellingfan is down <br/>"; }}
开车库门命令类:GarageDoorOpenCommand.php
<?phprequire_once 'Command.php';class GarageDoorOpenCommand implements Command{ private $_garage_door; public function __construct(GarageDoor $garageDoor){ $this->_garage_door = $garageDoor; }/* (non-PHPdoc) * @see Command::execute() */ public function execute() { // TODO Auto-generated method stub $this->_garage_door->open(); } public function undo() { // TODO Auto-generated method stub $this->_garage_door->close(); }}
关车库门命令:GarageDoorCloseCommand.php
<?phprequire_once 'Command.php';class GarageDoorCloseCommand implements Command{ private $_garage_door; public function __construct(GarageDoor $garageDoor){ $this->_garage_door = $garageDoor; }/* (non-PHPdoc) * @see Command::execute() */ public function execute() { // TODO Auto-generated method stub $this->_garage_door->close(); } public function undo() { // TODO Auto-generated method stub $this->_garage_door->open(); }}车库门类:GarageDoor.php
<?phpclass GarageDoor{ public function open(){ echo "the garagedoor is open <br/>"; } public function close(){ echo "the garagedoor is close <br/>"; }}
什么都不做的命令类:NoCommand.php
<?phprequire_once 'Command.php';class NoCommand implements Command{ public function execute() { }}
遥控器类:RemoteController.php
<?phprequire_once 'NoCommand.php';class RemoteController{ private $_onCommand = array(); private $_offCommand = array(); private $_undoCommand; public function __construct() { for ($i = 1; $i < 7; $i ++) { $this->_onCommand[$i] = new NoCommand(); $this->_offCommand[$i] = new NoCommand(); } $this->_undoCommand = new NoCommand(); } public function setOnAndOffCommand($key, Command $onCommand, Command $offCommand) { $this->_onCommand[$key] = $onCommand; $this->_offCommand[$key] = $offCommand; } public function onBottonWasPressed($key) { $this->_onCommand[$key]->execute(); $this->_undoCommand = $this->_onCommand[$key]; } public function offBottonWasPressed($key) { $this->_offCommand[$key]->execute(); $this->_undoCommand = $this->_offCommand[$key]; } public function undoBottonWasPressed() { $this->_undoCommand->undo(); }}
入口文件:index.php
<?php//初尝命令模式require_once 'Light.php';require_once 'LightOffCommand.php';require_once 'LightOnCommand.php';require_once 'GarageDoor.php';require_once 'GarageDoorCloseCommand.php';require_once 'GarageDoorOpenCommand.php';require_once 'CellingFan.php';require_once 'CellingFanDownCommand.php';require_once 'CellingFanUpCommand.php';require_once 'RemoteController.php';$light = new Light();$lightOnCommand = new LightOnCommand($light);$lightOffCommand = new LightOffCommand($light);$garageDoor = new GarageDoor();$garageDoorOpenCommand = new GarageDoorOpenCommand($garageDoor);$garageDoorCloseCommand = new GarageDoorCloseCommand($garageDoor);$cellingFan = new CellingFan();$cellingFanUpCommand = new CellingFanUpCommand($cellingFan);$cellingFanDownCommand = new CellingFanDownCommand($cellingFan);$remoteController = new RemoteController();$remoteController->setOnAndOffCommand(0, $lightOnCommand, $lightOffCommand);$remoteController->setOnAndOffCommand(1, $garageDoorOpenCommand, $garageDoorCloseCommand);$remoteController->setOnAndOffCommand(2, $cellingFanUpCommand, $cellingFanDownCommand);$remoteController->onBottonWasPressed(0);$remoteController->offBottonWasPressed(0);$remoteController->onBottonWasPressed(1);$remoteController->offBottonWasPressed(1);$remoteController->onBottonWasPressed(2);$remoteController->offBottonWasPressed(2);上面的代码中出现了一个NoCommand.php,如果没有设计这个类,当我们试图去调用没有被声明的命令类时,程序会报错,比如说我们去调用
$remoteController->onBottonWasPressed(3);因为并未对键值为3的$_onCommand进行赋值,程序将会报错,而现在初始化时每个键值被赋予为NoCommand命令类,就可以规避这种情形下的报错
我们再扩展一下,如果用户希望可以一键执行打开点电灯、打开风扇、打开车库门这一系列的操作怎么办呢?我们可以设计一组宏命令绑定在遥控器的某个按钮上供用户使用,具体实现代码如下所示:
宏命令类:MacroCommand.php
<?phprequire_once 'Command.php';class MacroCommand implements Command{ private $_commands; public function __construct(array $commands){ $this->_commands = $commands; }/* (non-PHPdoc) * @see Command::execute() */ public function execute() { // TODO Auto-generated method stub foreach ($this->_commands as $command){ $command->execute(); } }}
入口文件index.php变更为:
<?php// 初尝命令模式require_once 'Light.php';require_once 'LightOffCommand.php';require_once 'LightOnCommand.php';require_once 'GarageDoor.php';require_once 'GarageDoorCloseCommand.php';require_once 'GarageDoorOpenCommand.php';require_once 'CellingFan.php';require_once 'CellingFanDownCommand.php';require_once 'CellingFanUpCommand.php';require_once 'RemoteController.php';require_once 'MacroCommand.php';$light = new Light();$lightOnCommand = new LightOnCommand($light);$lightOffCommand = new LightOffCommand($light);$garageDoor = new GarageDoor();$garageDoorOpenCommand = new GarageDoorOpenCommand($garageDoor);$garageDoorCloseCommand = new GarageDoorCloseCommand($garageDoor);$cellingFan = new CellingFan();$cellingFanUpCommand = new CellingFanUpCommand($cellingFan);$cellingFanDownCommand = new CellingFanDownCommand($cellingFan);$macroOnCommand = new MacroCommand(array( $lightOnCommand, $garageDoorOpenCommand, $cellingFanUpCommand));$macroOffCommand = new MacroCommand(array( $lightOffCommand, $garageDoorCloseCommand, $cellingFanDownCommand));$remoteController = new RemoteController();/* $remoteController->setOnAndOffCommand(0, $lightOnCommand, $lightOffCommand);$remoteController->setOnAndOffCommand(1, $garageDoorOpenCommand, $garageDoorCloseCommand);$remoteController->setOnAndOffCommand(2, $cellingFanUpCommand, $cellingFanDownCommand);$remoteController->onBottonWasPressed(0);$remoteController->undoBottonWasPressed();$remoteController->offBottonWasPressed(0);$remoteController->undoBottonWasPressed();$remoteController->onBottonWasPressed(1);$remoteController->undoBottonWasPressed();$remoteController->offBottonWasPressed(1);$remoteController->undoBottonWasPressed();$remoteController->onBottonWasPressed(2);$remoteController->undoBottonWasPressed();$remoteController->offBottonWasPressed(2);$remoteController->undoBottonWasPressed(); */$remoteController->setOnAndOffCommand(3, $macroOnCommand, $macroOffCommand);$remoteController->onBottonWasPressed(3);$remoteController->offBottonWasPressed(3);
- php设计模式入门-命令模式
- 设计模式入门-策略模式(php版)
- 设计模式入门-代理模式(php版)
- php设计模式入门-观察者模式
- php设计模式入门-单例模式
- php设计模式入门-注册表模式
- 设计模式入门之命令模式Command
- PHP设计模式漫谈之命令模式
- PHP设计模式-命令模式
- php设计模式之命令模式
- PHP设计模式-命令模式
- php中的设计模式之--命令模式
- php设计模式之命令链模式
- PHP设计模式——命令模式
- php设计模式之命令链模式
- 设计模式之命令模式php示例
- php设计模式_命令模式
- 设计模式---命令模式
- 二进制中1的个数
- Android的MediaPlayer架构介绍
- Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contai
- 欧拉工程第23题:Non-abundant sums
- X86汇编快速入门
- php设计模式入门-命令模式
- UVA 1640(数位统计)
- hdu 1548 一维bfs大水题
- NYOJ 135 取石子(二)(博弈)
- JConsole监控远程Tomcat服务器
- 计算机视觉牛人汇总
- Git使用笔记
- Tomcat的三种模式及并发优化
- C语言的循环语句(4.24)