前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >php设计模式(十六):命令模式(Command)

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

作者头像
陈大剩博客
发布2023-05-12 08:39:06
2560
发布2023-05-12 08:39:06
举报

命令模式

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

问题

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

rm -rf
rm -rf

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

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

解决方法

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

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

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

UML

UML
UML

结构

Command:命令抽象类;一般会暴露一个 execute 方法; Delete、Create、Update:具体的命令类;设定接收者; Invoker:命令发送者;用于调用命令; Model: 命令接收者;负责执行操作;

代码示例

命令接口基类

代码语言:javascript
复制
/**
 * 命令模式接口基类
 */
abstract class Command
{
    /**
     * 模型
     * @var Model
     */
    public Model $model;

    /**
     * 命令名称
     * @var
     */
    public $name;

    /**
     * 执行方法
     * @return mixed
     * @author chendashengpc
     */
    abstract public function execute();

}

命令具体类

删除

代码语言:javascript
复制
/**
 * 删除
 */
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();
    }
}

新增

代码语言:javascript
复制
/**
 * 创建
 */
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();
    }

更新

代码语言:javascript
复制
/**
 * 更新
 */
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();
    }
}

调用类

代码语言:javascript
复制
/**
 * 调用类
 */
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)

代码语言:javascript
复制
/**
 * 具体接受者类(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 '新增命令';
    }
}

客户端使用

代码语言:javascript
复制
// 新建一个模型
$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();

输出

代码语言:javascript
复制
新增命令
更新命令

优缺点

优点

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

缺点

  • 代码可能会变得更加复杂,因为在发送者和接收者之间增 加了一个全新的层次。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-05-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 命令模式
  • 问题
  • 解决方法
  • UML
  • 结构
  • 代码示例
    • 命令接口基类
      • 命令具体类
        • 调用类
          • 具体接受者类(Model)
            • 客户端使用
            • 优缺点
              • 优点
                • 缺点
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档