当前位置: 首页 > news >正文

精读C++20设计模式——行为型设计模式:命令模式

精读C++20设计模式——行为型设计模式:命令模式

前言:Lets Command!

​ Command设计模式实际上不太Command。这个比较反直觉。因为Command设计模式压根就不是直接死命令对象到底怎么做事情。而是发送命令,接收对象根据发送者发送的命令执行代码。

命令模式干什么

​ 命令模式将我们对API的操作封装成命令,命令的调用就是对对象的操作。看起来好像没什么问题,比如说:

class BankAccount {int balance = 0;constexpr int overdraft_limit = -500;
public:void deposit(int amount) { balance += amount; }void withdraw(int amount) { if(balance - amount < overdraft_limit) return;blance -= amount;}
};

​ 我们把类完成了!现在我们可以这样做了。

struct Command { virtual void call() const = 0; };struct BankAccountCmd : Command
{BankAccount& ba;enum class AcceptableAction { deposit, withdraw } action;int amount;// BankAccountCmd init omittedvoid call() const override {switch(action){case deposit:// process all the deposit relativebreak;case withdraw:// process all the withdraw relativebreak;}  };
};

​ 你看到了嘛?我们现在立马就可以无任何侵入的做比直接调用显然更多的事情了:

BankAccount ba;
BankAccountCmd bacmd {ba, AcceptableAction::deposit, 500};
bacmd.call();

​ 完事。你发现我们完全可以对Command做额外的提交约束啊等一系列的事情,完全不用动BankAccount的任何代码——只要他自己相关的接口是稳定的!

​ 我们甚至还可以滚动回来!比如说我们小小的翻新一下Command(假设我们真的笃定Command是要支持撤回的)

struct Command { virtual void call() = 0; virtual void undo() = 0; 
};

​ 现在我们自然可以根据我们实现的逻辑的撤回操作依次的完成Command的接口,最后我们就会组合成一个非常具备代码整洁的命令链条——还是支持撤回操作的那种!

组合我们的命令:结合组合模式+命令模式

​ 一堆Command的有机组合是不是也是一个Command,或者说Command的正交组合显然还是一个Command。那么,我们就有理由编写出一个更好的组合Command

struct ComposedBankCommand : Command
{// register commandsvoid call() override {for(auto& cmd : composers)  cmd->call();};void undo() override {for(auto& cmd : composers)  cmd->call();}private:vector<Command*>	composers;
};

​ 但好像不对?如果我们中间的一个command失败了,其他的干脆就不应该调用——当然对于并行式的Command蔟完全没问题。这个是逻辑设计的差异。解决这个的办法也很好说——Command内部维护一个是否成功的操作就好了嘛!

总结:

解决什么问题

命令模式要解决的核心问题是把“动作”从调用者中剥离出来,使动作成为可传递、可存储、可组合、可撤销的对象。当程序中出现需要延迟执行、排队执行、撤销/重做、日志回放、网络传输或组合多个操作等需求时,直接在调用处硬编码调用逻辑会导致耦合、难以扩展与难以控制。命令模式把对某个接口/对象的“操作”封装成单独的对象(Command),从而把请求者与执行者解耦,同时把操作本身作为一等公民来处理(队列、日志、回滚、组合……都可以做)。

如何解决

命令模式通过定义一个统一的命令接口(比如 call() / execute(),必要时还加上 undo() / redo())来表示“要做的事”。每个具体命令包含执行该操作所需的接收者引用和参数。调用方只负责生成或提交命令对象,不直接操作接收者;命令可以被放入队列、写入日志、传到远端、组合成宏命令或在稍后执行。为支持撤销/补偿,命令可以维护执行前的状态(或借助 Memento),或者提供一个 undo() 方法做反向操作。为了支持异步、可靠性或回放,还可以给命令增加序列化/日志化能力。


各个变种的优劣对比
变种描述优点缺点典型适用场景
基本命令(Basic Command)最简形式:命令对象封装接收者和参数,实现 execute()实现简单,耦合低,便于扩展与测试。只适合同步、一次性调用,缺少撤销/持久化支持。简单的解耦、延迟执行需求。
可撤销命令(Undoable Command)命令实现 execute()undo() 或保存 Memento 做回滚。支持撤销/重做,用户体验好(编辑器、事务界面)。需要额外保存状态或实现反向操作,设计与边界条件复杂。文本编辑、图形编辑、事务局部回退。
组合命令 / 宏命令(Composite / Macro)把多个命令组合成一个命令;支持原子或顺序执行。易于复用、批量操作、一次执行多个子操作。失败处理复杂(部分成功如何回滚);错误传播要设计清楚。批处理、事务化工作流、复合操作。
http://www.dtcms.com/a/426685.html

相关文章:

  • petalinux 安装Openblass库
  • 织梦播放器网站网站建设简历自我评价
  • 大数据毕业设计选题推荐-基于大数据的全球经济指标数据分析与可视化系统-Hadoop-Spark-数据可视化-BigData
  • Spring Boot 整合 Redisson 实现分布式锁:实战指南
  • 国鑫发布新一代「海擎」服务器 全面兼容国内外主流OAM GPU
  • 百度电商MultiAgent视频生成系统
  • FRP v0.65.0 内网穿透专业指南(SSH + HTTP/HTTPS 一体化配置)
  • UNIX下C语言编程与实践20-UNIX 文件类型判断:stat 结构 st_mode 与文件类型宏的使用实战
  • 电脑网站开发手机上可以打开吗网站建设如何把代码
  • ROS2下利用遥控手柄控制瑞尔曼RM65-B机器人
  • SOC(安全运营中心)
  • 济南网站建设山东聚搜网推荐传媒公司招聘
  • C++ STL 深度解析:容器、迭代器与算法的协同作战
  • SPI主控的CS引发的读不到设备寄存器
  • 数据标注、Label Studio
  • 央链知播受权发布:图说《“可信资产 IPO + 数链金融 RWA” 链改 2.0 六方共识》
  • 【Proteus8.17仿真】 STM32仿真 0.96OLED 屏幕显示ds1302实时时间
  • 佛山做营销型网站建设wordpress修改域名后无法登陆
  • mysql数据库学习之常用函数(五)
  • 避坑实战!京东商品详情接口开发指南:分页优化、多规格解析与数据完整性保障
  • win10(十二)Nuitka打包程序
  • 【Rust GUI开发入门】编写一个本地音乐播放器(11. 支持动态明暗主题切换)
  • 自己做网站帮公司出认证证书违法吗上海定制网站建设公司
  • [论文阅读] AI + 软件工程(Debug)| 告别 “猜 bug”:TreeMind 用 LLM+MCTS 破解 Android 不完整报告复现难题
  • ESP32 + MCP over MQTT:通过大模型控制智能硬件设备
  • 五大关系数据库(sqlserver、mysql、oracle、pgsql、sqlite)的对象名称和转义字符
  • 央企云原生PaaS建设方案及案例集锦
  • 使用Django从零开始构建一个个人博客系统
  • 工业互联网的云原生转型路径
  • 做网站需要哪些素材建筑工程 技术支持 东莞网站建设