新闻中心

C++如何实现命令设计模式?C++请求封装与撤销功能实现【设计模式】

2025-12-15
浏览次数:
返回列表
命令模式在C++中通过将请求封装为Command接口对象实现解耦,支持参数化、排队、日志与撤销;Invoker调用execute()/undo()而不依赖Receiver细节,Receiver仅执行具体逻辑,命令对象应轻量、无状态或仅存必要上下文,撤销需缓存状态并用智能指针管理生命周期。

c++如何实现命令设计模式?c++请求封装与撤销功能实现【设计模式】

命令模式在C++中核心是把“请求”封装成对象,从而支持参数化、排队、日志、撤销等操作。关键在于定义统一的命令接口,让调用者(Invoker)不依赖具体操作细节,而接收者(Receiver)只负责执行实际逻辑。

命令接口与具体命令类

定义抽象基类 Command,声明虚函数 execute() 和可选的 undo();每个具体操作(如打开文件、保存、撤回)派生一个命令类,内部持有对 Receiver 的引用或所需数据。

  • Receiver 不直接被 Invoker 调用,而是由 Command 在 execute() 中调用其方法
  • 命令对象应尽量无状态,或仅保存执行必需的最小上下文(如文件名、旧文本、坐标)
  • 若需撤销,undo() 必须能恢复到 execute 前的状态,通常需在 execute 中缓存关键信息

支持撤销的命令栈管理

std::stack<:unique_ptr>> 管理已执行命令,每次 execute 后压入栈;调用 undo 时弹出栈顶并调用其 undo()。注意:不是所有命令都支持撤销(如“退出程序”),可加 isUndoable() 接口或用空实现。

  • 撤销后通常需禁用重做(Redo),若需支持,可额外维护一个 redo 栈,在 undo 时把命令移入 redo 栈
  • 避免裸指针,用智能指针管理命令生命周期,防止内存泄漏
  • 命令对象一般是一次性使用的,执行/撤销后可析构,无需复用

调用者(Invoker)解耦设计

Invoker 持有 Command* 或 std::function,但更推荐持有 Command 接口指针(或 std::unique_ptr),通过 setCommand() 注入不同命令。它不关心命令做什么,只负责触发 execute() 或 undo()。

QoQo QoQo

QoQo是一款专注于UX设计的AI工具,可以帮助UX设计师生成用户角色卡片、用户旅程图、用户访谈问卷等。

QoQo 172 查看详情 QoQo
  • 可扩展为支持宏命令(MacroCommand):聚合多个子命令,统一 execute/undo
  • 菜单项、快捷键、按钮等 UI 元素均可作为 Invoker,绑定不同命令实例
  • Invoker 可记录命令执行时间、失败重试策略,或转发给日志模块

一个简明示例:文本编辑器的撤销操作

假设 Receiver 是 TextDocument,有 insert(text) 和 deleteLast() 方法。命令类 InsertCommand 在构造时保存待插入文本,在 execute() 中调用 insert(),在 undo() 中调用 deleteLast()(前提是知道删多少字符——所以它还需缓存 length)。

  • 构造 InsertCommand(doc, "hello") → 缓存 doc 和 "hello" 长度 5
  • execute() → doc.insert("hello")
  • undo() → doc.deleteLast(5)
  • Invoker(如 Editor 类)持有一个 std::stack,每次成功 execute 后 push(std::move(cmd))

基本上就这些。命令模式在 C++ 中不复杂,但容易忽略内存管理和撤销状态一致性。只要接口清晰、职责分明,就能自然支持请求队列、事务回滚和用户级撤销功能。

以上就是C++如何实现命令设计模式?C++请求封装与撤销功能实现【设计模式】的详细内容,更多请关注其它相关文章!


# 做什么  # 双鸭山市关键词seo排名优化  # 鄂州网站建设步骤  # 临沂网站如何推广  # 盛大文学网站建设  # 罗村网站建设方案书  # 靠谱seo整站优化  # 营销推广岗位奖金  # 株洲seo外包公司  # 谷歌搜索seo站群  # 灵寿网站优化多少钱  # 执行时间  # mac  # 是由  # 调用者  # 多个  # 就能  # 若需  # 具体操作  # 如何用  # 如何实现  # red  # c++  #  


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: mcjs网页版流畅运行 mcjs低配电脑畅玩入口  MAC怎么让Dock栏只显示当前运行的应用_MAC终端命令实现极简Dock栏  2025-2030年全球乘用车销量预测:新能源成增长主力  深入理解J*a链表中的IPosition接口与使用  深入理解Promise链:如何在catch后中断then的执行  探索高级语言到C/C++的转译路径:以Go为例及内存管理策略  在J*a中如何使用Exception包装底层异常_异常包装与信息传递方法说明  qq游戏网页版直接玩_qq游戏免下载快速入口  Django模型中自动计算可用余额的实现方法  Win11文件资源管理器卡顿怎么修 Win11重置资源管理器进程优化响应速度【修复方法】  如何在Promise链中优雅地中断后续then执行  QQ邮箱官方邮箱登录入口 QQ邮箱网页版快速访问  知音漫客正版漫画平台_知音漫客官网账号登录  大麦的“候补”是什么意思 大麦候补购票规则【详解】  Fabric Mod开发:在1.19.3+版本中正确添加自定义物品并管理物品组  支付宝解绑银行卡步骤_支付宝如何解除绑定银行卡  Golang如何实现微服务鉴权与权限控制_Golang微服务鉴权与权限管理实践  Sublime怎么配置Nim语言环境_Sublime Nim代码高亮与补全  Win11输入法不见了怎么办_Windows11恢复语言栏显示方法  QQ邮箱官网登录入口 QQ邮箱网页版邮箱快速登录  抖音从哪里进入网页版_抖音官方入口链接  谷歌google账号怎么注册账号 谷歌账号注册官方流程  在J*a里如何理解依赖关系的方向_依赖方向在模块结构中的作用  CKEditor 5 自定义构建在React应用中渲染失败的调试与解决  CSS条件样式无法按设备触发怎么排查_media条件语句正确设置解决触发问题  cad怎么合并重叠的线段_cad清理重复重叠线条的操作方法  QQ网页版官方账号入口 QQ网页版网页版登录指南  Pandas DataFrame 高效批量赋值:告别循环与笛卡尔积误区  qq音乐在线播放入口_qq音乐电脑版登录链接  J*aScript设计模式实践_j*ascript代码优化  Golang如何实现Web文件静态资源服务器_Golang静态资源服务器开发与实践  2306选座时如何选靠窗位置_12306选座靠窗座位查看方法解析  CSS布局中意外空白:解决padding-top导致的顶部间距问题  Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】  照顾宝贝2小游戏点击立即在线玩  AO3最新官网入口公告_2025AO3镜像站实时查询方法  Win11 USB传输速度慢怎么解决 Win11 USB驱动更新与设置  12306选座如何查看座位示意图_12306座位示意图解读与使用  Kafka Streams中基于消息头条件过滤消息的实现指南  韩小圈电脑版在线入口_网页版免费登录地址  MongoDB Aggregation:在嵌套对象数组中精确匹配ObjectId  C++ explicit关键字防止隐式转换_C++构造函数安全规范  内存检查:在VS Code中调试C++时的内存视图  TypeScript/J*aScript:高效查找数组中首个唯一ID对象  期待已久:小米17 Ultra、小米首款NAS本月登场  163邮箱登录密码 163邮箱忘记密码找回  uc浏览器网页版入口 uc浏览器网页版最新网址  移动端XML文件怎么转换成Excel 手机和平板上的解决方案  知音漫客官网漫画下载_知音漫客网页版阅读记录  c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析 

搜索