陈大剩博客

php设计模式(十六):命令模式(Command)

  • 陈大剩
  • 2023-05-11 17:34:11
  • 53

命令模式

命令模式又称为:动作、事务、Action、Transaction、Command。命令是一种行为设计模式,可将请求转换为一个包含与请求相关的所有信息的独立对象。该转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。

问题

大家肯定经常是用命令的,命令一敲,啥都不爱,这个笑话大家肯定看过:
rm -rf

这样一操作,你可能离包吃包住不远了,那么我们有没有一种办法可以在命令生效前,可撤销之前输入的命令呢?

比如我们常用的 ORM 模型,ORM 一旦发送命令给你数据库,那我们的数据永远找不回了。

解决方法

其实我们可以在 客户端命令执行者 中间添加一个中间人 命令发送者,命令发送者负责 接收客户端命令发送命令,所有要执行的命令都在 命令发送者 里,可支持:撤回、重写、更新,这样的设计模式我们称为“命令模式”。

命令模式就和名字一样,比较适合执行命令,命令发送者只管调用具体命令类中的 execute() 方法,然后在具体命令类中设定命令接收者,可以消除命令发送者和命令接受者之间的耦合,并且可以方便的扩展新命令;

流程:先将命令注册到命令执行者中,再将需要执行的命令(如:Create、Update、Delete)发给 命令发送者命令发送者 命令类中的 execute() 方法发送命令执行。

UML

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();

输出

新增命令
更新命令

优缺点

优点

  • 单一职责原则。 可以解耦触发和执行操作的类。
  • 开闭原则。 可以在不修改已有客户端代码的情况下在程序 中创建新的命令。
  • 可以实现撤销和恢复功能。
  • 可以实现操作的延迟执行。
  • 可以将一组简单命令组合成一个复杂命令。

缺点

  • 代码可能会变得更加复杂,因为在发送者和接收者之间增 加了一个全新的层次。
分享到:
0

说点儿什么吧

头像

表情

本站由陈大剩博客程序搭建 | 湘ICP备2023000975号| Copyright © 2017 - 陈大剩博客 | 本站采用创作共用版权:CC BY-NC 4.0

站长统计| 文章总数[100]| 评论总数[9]| 登录用户[22]| 时间点[103]

logo

登入

社交账号登录