本文已参与「新人创作礼」活动,一起开启掘金创作之路。
设计模式之命令模式--php实现命令模式
命令模式就是把命令封装成对象。
将一个请求封装为对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录日志,以及支持可撤销的操作。
为什么要使用命令模式
命令模式有哪些好处呢?
- 他能较容易的设计一个命令队列
- 在需要的情况下,可以较容易的将命令写入日志
- 允许接受请求的一方决定是否要否决请求
- 可以容易的实现对请求的撤销和重做
- 加入新的命令类更加容易
命令模式把请求一个操作的对象和直到怎么执行一个操作的对象分隔开。
比如服务员把操作的请求者客户和操作的执行者厨师分离开,把客户的命令传递给厨师。
- 并可以传递一系列命令
- 可以把命令记录下来
- 可以说这个菜没有了否决请求
- 可以客户不要菜了撤销请求
- 可以加入新的菜品命令
比如自如管家把操作的请求者租户和操作的执行者房东分离开,把租户的需求传递给房东。
- 可以传递一系列需求,比如要修电视,修洗衣机
- 可以把命令记录下来,然后一起告诉房东
- 可以说这个不在服务范围内
- 可以租户修好了,说不用修了
- 可以加入新的需求命令
当然这个比喻不太准确,哈哈哈,自如更像中介模式把所有的房东和租户分离开。
php实现命令模式
我们先找到一个房东,房东类可以修电视,修洗衣机
/**
* 命令模式
* 房东类,提供修洗衣机修电视服务
*/
class receiver {
/**
* 修电视
*/
public function TV() {
dump('房东修电视');
}
/**
* 修洗衣机
*/
public function wash() {
dump('房东修洗衣机');
}
}
有了房东我们接下来找一个自如管家,让管家联系房东。
/**
* 命令模式
* 自如管家,负责接收命令传递给房东
*/
class invoke {
private $arr = [];
/**
* 设置命令
*/
public function setCommand(Command $command) {
$this->arr[] = $command;
}
/**
* 撤销命令
*/
public function cancel(Command $command) {
foreach($this->arr as $key => $com) {
if ($com == $command) {
unset($this->arr[$key]);
}
}
}
/**
* 执行命令
*/
public function exec() {
foreach($this->arr as $command) {
$command->exec();
}
}
}
我们现在可以像管家下命令了,哎,没有命令类啊,那我们现在增加命令。
/**
* 命令模式
* 命令抽象类,所有具体命令继承这个类
*/
abstract class Command {
protected $receiver;
/**
* 创建命令的时候要告诉这个命令是给谁执行的,所以要传入执行者
*/
public function __construct(receiver $receiver) {
$this->receiver = $receiver;
}
public abstract function exec();
}
/**
* 命令模式
* 修电视命令
*/
class tv extends Command{
/**
* 把命令告诉真正的执行者
* 让执行者修电视
*/
public function exec() {
$this->receiver->tv();
}
}
/**
* 命令模式
* 修洗衣机命令
*/
class wash extends Command{
/**
* 把命令告诉真正的执行者
* 让执行者修洗衣机
*/
public function exec() {
$this->receiver->wash();
}
}
好了,有了命令,我们可以给管家下命令了。
$invoke = new invoke();
//租户告诉管家找房东修电视
$invoke->setCommand(new tv(new receiver));
//租户告诉管家找房东修洗衣机
$invoke->setCommand(new wash(new receiver));
//管家找房东去了
$invoke->exec();
这就是命令模式,不过在程序中,我还没想好有啥场景使用这个模式。。。
代码放在了我的github上面。