B6:命令模式 Command
将一个请求封装成一个对象,从而可以用不同的请求对象对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作.
与状态模式和责任链模式的区别是,命令模式设定一次,统一执行
使用场景:
1.可设计一个队列
2.较容易将命令计入日志
3.允许接收的一方是决定是否否决请求
4.可以实现对请求的撤销和重做
5.加入新的命令类不影响其他的类.
6.把请求一个操作的对象与执行操作的对象分离开.
UML
示例代码:
// 命令接口 abstract class Command { protected $receiver; public function __construct(Receiver $receiver) { $this->receiver = $receiver; } // 执行命令 abstract public function execute($params); // 撤销命令 abstract public function undo(); } // 具体命令执行者 class UserCommand extends Command { public function execute($params) { return $this->receiver->command($params); } public function undo() { return $this->receiver->undo(); } } // 具体命令执行者2 class EmailCommand extends Command { public function execute($params) { return $this->receiver->command($params); } public function undo() { return $this->receiver->undo(); } } // 命令接受者接口 interface Receiver { public function command($params); public function undo(); } // 命令接受者1 class User implements Receiver { public function command($parms) { echo '写入:用户增加成功' . $parms; } public function undo() { echo '撤销了日志写入'; } } // 命令接受者2 class Email implements Receiver { public function command($parms) { echo '发送邮件' . $parms; } public function undo() { echo '撤销了发送邮件'; } } // 命令请求者 class Invoker { protected $command; public function setCommand(Command $command) { $this->command = $command; } public function execute($params) { return $this->command->execute($params); } public function undo() { return $this->command->undo(); } } $receiver1 = new User(); $receiver2 = new Email(); $invoker = new Invoker(); $invoker->setCommand(new UserCommand($receiver1)); $invoker->execute('jack'); $invoker->undo(); $invoker->setCommand(new EmailCommand($receiver2)); $invoker->execute('jack'); $invoker->undo();
另一个例子:
客户点菜,服务员向厨师发送炒菜命令
/** * 厨师,命令接受者与执行者 * Class Cook */ class Cook { public function chaocai() { echo '开始炒菜了'; } public function zuotang() { echo '开始做汤'; } } // 命令接口 abstract class Command { protected $cook; public function __construct(Cook $cook) { $this->cook = $cook; } } // 命令1 class Chaocai extends Command { public function chaocaiCommand() { $this->cook->chaocai(); } } // 命令2 class Zuotang extends Command { public function zuotangCommand() { $this->cook->zuotang(); } } // 命令请求者,服务员 class Fuyuwuan { private $chaocai; private $zuotang; public function __construct(Chaocai $chaocai, Zuotang $zuotang) { $this->chaocai = $chaocai; $this->zuotang = $zuotang; } public function callChaocai() { $this->chaocai->chaocaiCommand(); } public function callZuotang() { $this->zuotang->zuotangCommand(); } } // 客户 $cook = new Cook(); // 新建厨师 // 命令 $chaocai = new Chaocai($cook); $zuotang = new Zuotang($cook); $fuwuyuan = new Fuyuwuan($chaocai, $zuotang); // 新建服务员 $fuwuyuan->callChaocai(); // 向服务员点单