php设计模式(十六):命令模式(Command)
- 陈大剩
- 2023-05-11 17:34:11
- 923
命令模式
命令模式又称为:动作、事务、Action、Transaction、Command。命令是一种行为设计模式,可将请求转换为一个包含与请求相关的所有信息的独立对象。该转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。
问题
大家肯定经常是用命令的,命令一敲,啥都不爱,这个笑话大家肯定看过:
这样一操作,你可能离包吃包住不远了,那么我们有没有一种办法可以在命令生效前,可撤销之前输入的命令呢?
比如我们常用的 ORM 模型,ORM 一旦发送命令给你数据库,那我们的数据永远找不回了。
解决方法
其实我们可以在 客户端 和 命令执行者 中间添加一个中间人 命令发送者,命令发送者负责 接收客户端命令 和 发送命令,所有要执行的命令都在 命令发送者 里,可支持:撤回、重写、更新,这样的设计模式我们称为“命令模式”。
命令模式就和名字一样,比较适合执行命令,命令发送者只管调用具体命令类中的 execute() 方法,然后在具体命令类中设定命令接收者,可以消除命令发送者和命令接受者之间的耦合,并且可以方便的扩展新命令;
流程:先将命令注册到命令执行者中,再将需要执行的命令(如:Create、Update、Delete)发给 命令发送者 , 命令发送者 命令类中的 execute() 方法发送命令执行。
UML
结构
Command:命令抽象类;一般会暴露一个 execute 方法;
Delete、Create、Update:具体的命令类;设定接收者;
Invoker:命令发送者;用于调用命令;
Model: 命令接收者;负责执行操作;
代码示例
命令接口基类
/**
* 命令模式接口基类
*/
abstract class Command
{
/**
* 模型
* @var Model
*/
public Model $model;
/**
* 命令名称
* @var
*/
public $name;
/**
* 执行方法
* @return mixed
* @author chendashengpc
*/
abstract public function execute();
}
命令具体类
删除
/**
* 删除
*/
class Delete extends Command
{
/**
* 初始化函数
* @param Model $model
*/
public function __construct(Model $model)
{
$this->name = 'delete';
$this->model = $model;
}
/**
* 执行函数
* @return mixed|void
* @author chendashengpc
*/
public function execute()
{
return $this->model->delete();
}
}
新增
/**
* 创建
*/
class Create extends Command
{
/**
* 初始化函数
* @param Model $model
*/
public function __construct(Model $model)
{
$this->name = 'create';
$this->model = $model;
}
/**
* 执行函数
* @return mixed|void
* @author chendashengpc
*/
public function execute()
{
return $this->model->create();
}
更新
/**
* 更新
*/
class Update extends Command
{
/**
* 初始化函数
* @param Model $model
*/
public function __construct(Model $model)
{
$this->name = 'update';
$this->model = $model;
}
/**
* 执行函数
* @return mixed|void
* @author chendashengpc
*/
public function execute()
{
return $this->model->update();
}
}
调用类
/**
* 调用类
*/
class Invoker
{
protected $command = [];
/**
* 设置命令
* @param Command $command
* @return void
* @author chendashengpc
*/
public function setCommand(Command $command)
{
$this->command[$command->name] = $command;
}
/**
* 撤销命令
* @return void
* @author chendashengpc
*/
public function revoke(Command $command)
{
if (isset($this->command[$command->name])) {
unset($this->command[$command->name]);
}
}
/**
* 执行命令
* @return void
* @author chendashengpc
*/
public function execute()
{
foreach ($this->command as $command) {
echo $command->execute() . PHP_EOL;
}
}
}
具体接受者类(Model)
/**
* 具体接受者类(Model类)
*/
class Model
{
/**
* 删除
* @return void
* @author chendashengpc
*/
public function delete()
{
return '删除命令';
}
/**
* 更新
* @return void
* @author chendashengpc
*/
public function update()
{
return '更新命令';
}
/**
* 新增
* @return string
* @author chendashengpc
*/
public function create()
{
return '新增命令';
}
}
客户端使用
// 新建一个模型
$model = new Model();
$create = new Create($model);
$update = new Update($model);
$delete = new Delete($model);
// 设置一个调用者
$invoker = new Invoker();
$invoker->setCommand($create);
$invoker->setCommand($update);
$invoker->setCommand($delete);
$invoker->revoke($delete);
$invoker->execute();
输出
新增命令
更新命令
优缺点
优点
- 单一职责原则。 可以解耦触发和执行操作的类。
- 开闭原则。 可以在不修改已有客户端代码的情况下在程序 中创建新的命令。
- 可以实现撤销和恢复功能。
- 可以实现操作的延迟执行。
- 可以将一组简单命令组合成一个复杂命令。
缺点
- 代码可能会变得更加复杂,因为在发送者和接收者之间增 加了一个全新的层次。