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

news/2025/10/4 19:30:47/文章来源:https://www.cnblogs.com/wzzkaifa/p/19125846

精读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 omitted
void call() const override {
switch(action){
case deposit:
// process all the deposit relative
break;
case withdraw:
// process all the withdraw relative
break;
}
};
};

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

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 commands
void 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.mzph.cn/news/927473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Apache Beam入门教程:统一批流处理模型 - 教程

Apache Beam入门教程:统一批流处理模型 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

详细介绍:关于[汉芝电子低调获取证书,及生产各类加密产品]这档事

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

中国建设银行网站首页joy怎样添加字体到wordpress

目录 ★ 工作队列介绍代码演示测试注意点1&#xff1a;注意点2&#xff1a; ★ 工作队列介绍 工作队列&#xff1a; 就是让多个消费者竞争消费同一个消息队列的消息&#xff0c;相当于多个消费者共享消息队列。 ▲ RabbitMQ可以让多个消费者竞争消费同一个消息队列 ▲ 消息队…

华梦服饰网站建设中wordpress临时关闭站点

&#xff08;四&#xff09;无人机技术 1.无人作战飞机1.1 美国空军披露可与下一代战斗机编组作战的协同式无人作战飞机项目1.2 俄罗斯无人作战飞机取得重要进展 2.支援保障无人机2.1 欧洲无人机项目通过首个里程碑2.2 美国海军继续开展MQ-25无人加油机测试工作 3.微小型无人机…

花卉物流园做网站的素材phpcms做网站建栏目

1.关注点分离&#xff1a;每个功能最少会被切分为M-V-C三个部分&#xff0c;让开发者一次只需要关注一个部分&#xff0c;进而降低复杂难度&#xff0c;提高开发效率2.分层负责&#xff1a;明确切割&#xff0c;M-V-C三个部分并行开发3.自由操控HTML&#xff1a;在ASP.Net MVC中…

网站建设技术难题物流推广做哪个网站

在3dMax中如何把三维物体转化为由样条线构成的对象&#xff1f;通常这样的场景会出现在科研绘图或一些艺术创作当中&#xff0c;下面给大家详细讲解一种3dmax三维物体转样条线的方法。 第一部分&#xff1a;用粒子填充3D对象&#xff1a; 1.创建一个三维对象&#xff08;本例…

自适应h5网站模板wordpress wordcloud

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇利用OpenCV4.9制作自己的线性滤波器&#xff01; 下一篇 :OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 …

C# 与 C/C++ 互操作

本文介绍 C# 与 C/C++ 互操作的方法,尤重点介绍 P/Invoke。本文介绍 C# 与 C/C++ 互操作的方法,尤重点介绍 P/Invoke。 为什么要互操作? 主要有两个原因:用 C/C++ 编写算法核心代码,提高程序性能。 有一些库 / AP…

实用指南:gitlab-runner 再次实践中理解和学习

实用指南:gitlab-runner 再次实践中理解和学习pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

企业网站禁忌南京平面设计师联盟

一、实验目的&#xff1a; 1、掌握SQL SERVER的身份验证方式。 2、掌握SQL SERVER的权限。 3、掌握给数据库的用户和角色赋予权限和从用户和角色收回权限。 4、掌握GRANT&#xff0c;REVOKE&#xff0c;DENY的用法。 二、实验内容&#xff1a; 1、将SQL SERVER服务器的安全…

2025年7月28日当周关键漏洞汇总分析

美国网络安全和基础设施安全局(CISA)发布了2025年7月28日当周的漏洞公告,包含148个高危漏洞、157个中危漏洞和32个低危漏洞,涉及多个主流软件和系统,包括代码编辑器、代理服务器、内容管理系统等。漏洞摘要 - 2025年…

完整教程:Ref 和 Reactive 响应式原理剖析与代码实现

完整教程:Ref 和 Reactive 响应式原理剖析与代码实现pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&qu…

电子商务型网站建设免费自建网站

Java Web项目的层次结构及常见分包 Web项目中的层次 ControllerServiceDaoController层&#xff1a;表现层&#xff08;视图&#xff09;层。用来显示数据和接收用户数据Service层&#xff1a;业务逻辑层&#xff0c;用来处理页面。先写接口&#xff0c;后写实现类Dao层&#…

如何网上快速接网站开发订单手机网站进不去怎么办

场景介绍 小明接到学校老师安排的任务&#xff0c;需要批量将班级里同学们拍的普通照片转换为素描图&#xff0c;供课堂游戏使用&#xff0c;于是求助到程序员老爸&#xff0c;机智的程序员老爸分分钟用几行Python代码解决&#xff1a;在阿里云Serverless函数计算服务中部署普…

临安市住房和建设局网站深圳市网站推广公司

一. 背景 距离上一篇JS文章已经20天&#xff0c;经重新总结发现&#xff0c;上一篇概况的有点浅显&#xff0c;适合初学js的入门了解&#xff0c;但对于已经学习js一段时间的人&#xff0c;或者是想系统的了解JS体系&#xff0c;接下来的文章可能会更有帮助。 该系列博客的书写…

荣县住房和城乡建设厅网站wordpress收费缓存插件

文章目录 一、实验背景与目的二、实验拓扑三、实验需求四、实验解法1. PC 配置 IP 地址2. PC3 属于 Vlan10&#xff0c;PC4 属于 Vlan20&#xff0c;配置单臂路由实现 Vlan10 和 Vlan20 三层互通3. 测试在 PC3 上 Ping PC4 &#xff0c;可以 Ping 通 PC4 摘要&#xff1a; 本文…

【自然语言处理】文本规范化知识点梳理与习题总结 - 教程

【自然语言处理】文本规范化知识点梳理与习题总结 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas…

Rocky Linux 8 远程管理配置指南(宿主机 VNC + KVM 虚拟机 VNC) - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

公司做网站能抵扣进项税吗西安便宜做网站

思路&#xff1a;无论vue还是react打包都会有dist文件夹&#xff0c;内部有index.html。我是想根据index.html中的script src地址是否改变&#xff0c;判断项目是否有新内容。 具体代码如下 首先先拿到生产环境中index.html文本&#xff0c;由于是单页面应用使用fetch(/?_st…

西安企业网站制作公司wordpress 前端优化

接上一篇:企业实战_04_MyCat常用配置文件详解 https://gblfy.blog.csdn.net/article/details/100112080 文章目录1. 加密简述2. 加密目录3. 执行加密4. 添加加密属性5. 添加密文6. 测试是否可用声明&#xff1a;需要提前安装mysql Linux centos7 安装 MySQL5.7.x 1. 加密简述 …