0

0

c++如何实现命令模式_c++请求封装与撤销功能【核心】

穿越時空

穿越時空

发布时间:2026-02-16 11:01:54

|

469人浏览过

|

来源于php中文网

原创

命令模式核心结构是抽象基类command含execute()/undo(),具体命令持receiver引用;生命周期由智能指针或栈管理,状态快照需在execute()开头保存,撤销依赖准确记录而非重算,异步请求应由executor调度而非command自执行。

c++如何实现命令模式_c++请求封装与撤销功能【核心】

命令模式的核心结构怎么搭

命令模式本质是把「请求」封装成对象,让调用者(Invoker)和执行者(Receiver)解耦。C++里最直接的做法是定义抽象基类 Command,含纯虚函数 execute() 和可选的 undo();每个具体命令(如 LightOnCommandSaveDocumentCommand)继承它,并持有对 Receiver 的引用或指针。

关键点不是“怎么写类”,而是“谁负责生命周期管理”:如果 Command 对象需要被反复重用或跨线程传递,必须用智能指针(std::shared_ptr<command></command>);若只在栈上短时存在(比如 GUI 按钮点击后立刻执行),直接传值或栈对象更轻量。

  • Receiver 通常不继承接口,只是普通业务类,命令类内部调用其公有方法
  • 避免在 Command 构造时做耗时操作(如文件打开、网络连接),应延迟到 execute()
  • 若需支持参数化命令(比如“撤销第3次保存”),把必要状态存为成员变量,而非依赖外部上下文

撤销功能为什么常出 bug

撤销不是简单地反向调用 undo() —— 它依赖命令对象能准确记录执行前的状态。常见错误是:在 execute() 中修改了 Receiver 的状态,但 undo() 试图恢复时发现原始值已丢失。

典型翻车场景:TextEditor::deleteSelection() 执行后删掉了文本,但 DeleteCommand 没保存被删内容,undo() 只能空白恢复。正确做法是在 execute() 开头就拷贝关键状态(如字符串片段、坐标、ID 列表)。

立即学习C++免费学习笔记(深入)”;

Kive
Kive

一站式AI图像生成和管理平台

下载
  • 不要在 undo() 里重新计算原始值(比如“用当前光标位置反推上次删除范围”),不可靠
  • 涉及资源(文件句柄、内存块),undo() 必须能安全释放或回滚,否则引发 double-free 或泄漏
  • 复合命令(MacroCommand)的 undo() 必须逆序执行子命令的 undo(),顺序错会导致状态混乱

如何安全封装 C++ 请求(尤其是异步/多线程)

命令模式天然适合封装请求,但 C++ 原生不带协程或 await,所以“请求封装”往往指向两个方向:一是包装同步调用便于统一调度(如日志、重试、超时),二是桥接异步 API(如 std::async、回调函数、std::promise)。

重点在于隔离副作用:一个 HttpRequestCommand 对象不应自己启动线程,而应由专用的 CommandExecutor 负责调度。这样既能复用连接池,又能集中处理异常和超时。

  • 异步命令的 execute() 应返回 std::future<void></void> 或自定义 handle,而非阻塞等待
  • 撤销网络请求时,不能只取消本地任务,要调用底层 cancel 接口(如 curl_easy_cleanup() 或 HTTP client 的 cancel() 方法)
  • 避免在 Command 里捕获 std::exception_ptr 后裸存——要用 std::optional<:exception_ptr></:exception_ptr> 显式标记是否出错

std::function 能替代 Command 类吗

可以,但不推荐用于需要撤销或持久化的场景。用 std::function<void></void> 封装执行逻辑很简洁,但它无法自然携带 undo 行为、无法序列化、无法查询类型信息,且闭包捕获的对象生命周期难管控。

例如:auto cmd = [&editor]() { editor.save(); }; —— 这个 lambda 如果被存入队列延后执行,而 editor 已析构,运行时崩溃不可避免。

  • 仅当命令是临时、单次、作用域明确(如局部回调)时,std::function 是合理选择
  • 需要撤销、重做、日志审计、跨模块传递时,必须用具名类继承 Command,并显式管理状态与资源
  • 混合使用可行:让具体 Command 内部用 std::function 存储执行逻辑,但自身仍承担生命周期、undo、序列化职责

真正麻烦的从来不是写几个虚函数,而是决定哪些状态该快照、哪些资源必须配对管理、以及在多线程下谁负责 delete 那个 new Command 出来的对象。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

552

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

216

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1553

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

640

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

925

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

876

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

185

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

89

2025.08.07

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

283

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.6万人学习

C 教程
C 教程

共75课时 | 4.8万人学习

C++教程
C++教程

共115课时 | 18万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号