设计模式心得:三——命令模式
时间:2010-10-14 来源:陌路vs追忆
继续设计模式心得体验——命令模式。
命令模式: 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
一般在命令模式中有三个元素,invoker、command、receive。command 是一个抽象类或者也可以是个接口,它封装了一个execute方法,一般在command初始化的时候接受一个receive参数,而execute就是执行该receive的某些方法。invoker是请求者,它自身可以存储一个或者一组command的子类,然后在某种情况下按顺序执行这些command的execute方法。当然你也就可以记录下这些命令,或者撤销。invoker就不需要知道receive怎么做的它只需要知道command有execute方法就行了,不管它是怎么做的,这样就和receive解耦了。
在生活中的命令模式很多,比如你去餐馆吃饭,服务员给你拿了菜单,你写下几个菜,服务员将你点的菜记下来,然后交给厨师去做,在这其中,服务员就扮演invoker的角色,他不需要知道厨师怎么烧菜的,他只要将订单(command组)交给厨师就好。
命令模式一般被用来解决类似队列,记录日志,有撤销操作等类型的问题,invoker是这个核心,它能保证命令的有序执行并且可以记录下他们或者撤销操作,而不需要管这些命令是什么,只要是继承了command命令就行。
从这个模式中我学到了,封装的好处和抽象(或者说接口),用抽象或者接口定义的execute保证了invoker每次调用command的子类时execute都不会出错,所以invoker可以保证队列,日志的正常运行或撤销,而封装好了的execute方法让invoker与具体实现解耦,不用管到底它是怎么实现的。
下面贴下该模式的代码:
代码
<?php
//抽象命令类
abstract class Command {
protected $_r;
public function __construct(Receiver $r)
{
$this->_r = $r;
}
abstract public function execute();
}
//接受命令者(真正的执行者)
class Receiver {
private $_name;
//这里初始化不同的接受者
function __construct($name)
{
$this->_name = $name;
}
function kaoyrc()
{
echo $this->_name . '在烤羊肉串<br />';
}
function kaojc()
{
echo $this->_name . '在烤鸡翅<br />';
}
}
class Invoker {
private $_commands = array();
function setCommand(Command $cmd)
{
$this->_commands[] = $cmd;
}
function execute()
{
foreach ($this->_commands as $cmd)
{
$cmd->execute();
}
}
}
//这个是烤羊肉串的命令
class kaoyrcCommand extends Command {
public function execute()
{
$this->_r->kaoyrc();
}
}
//这个是考鸡翅的命令
class kaojcCommand extends Command {
public function execute()
{
$this->_r->kaojc();
}
}
$zs = new Receiver('张三'); //初始化接受者张三
$ls = new Receiver('李四'); //初始化接受者李四
$waiter = new Invoker(); //创建服务员
$zskaoyrc = new kaoyrcCommand($zs); //创建让张三烤羊肉串的命令
$zskaojc = new kaojcCommand($zs); //创建让张三烤鸡翅的命令
$lskaojc = new kaojcCommand($ls); //创建让李四烤鸡翅的命令
//将命令报给服务员让他处理
$waiter->setCommand($zskaoyrc);
$waiter->setCommand($zskaojc);
$waiter->setCommand($lskaojc);
$waiter->execute(); //将命令组报给接受者(解决者)
?>
// 结果
// 张三在烤羊肉串
// 张三在烤鸡翅
// 李四在烤鸡翅