新闻中心
C++如何实现一个命令模式_C++将请求封装成对象以实现解耦和可撤销操作
命令模式将请求封装为对象,实现发送者与接收者的解耦,支持撤销、重做和延迟执行;在C++中通过Command接口、具体命令、接收者、调用者和客户端协作完成,可用于GUI操作、事务管理等场景。

命令模式是一种行为设计模式,它将请求封装成对象,从而使你可以用不同的请求、队列、日志记录来参数化其他对象。在C++中实现命令模式,能有效解耦发送者和接收者,并支持撤销、重做、延迟执行等高级功能。
命令模式的核心思想
命令模式的关键在于把“操作”变成一个对象——即命令对象。这个对象知道要执行什么操作、由谁来执行,并可以触发执行。这样,调用方不需要了解具体执行逻辑,只需要持有命令对象并调用其执行方法即可。
主要角色包括:
- Command(命令接口):定义执行操作的接口,通常包含execute()和可选的undo()
- ConcreteCommand(具体命令):实现命令接口,绑定一个接收者,并在execute中调用接收者的方法
- Receiver(接收者):真正执行操作的对象
- Invoker(调用者):持有命令对象,负责触发命令执行
- Client(客户端):创建命令对象并绑定接收者
基本实现示例
下面是一个简单的文本编辑器中的“打开文件”和“保存文件”命令的实现:
#include <iostream>
#include <string>
#include <stack>
<p>// 接收者:处理实际操作
class TextEditor {
public:
void openFile(const std::string& filename) {
std:
:cout << "打开文件: " << filename << "\n";
}</p><pre class='brush:php;toolbar:false;'>void s*eFile() {
std::cout << "保存当前文件\n";
}};
PictoGraphic
AI驱动的矢量插图库和插图生成平台
133
查看详情
// 命令基类 class Command { public: virtual ~Command() = default; virtual void execute() = 0; virtual void undo() = 0; };
// 具体命令:打开文件 class OpenFileCommand : public Command { private: TextEditor* editor; std::string filename;
public: OpenFileCommand(TextEditor* e, const std::string& f) : editor(e), filename(f) {}
void execute() override {
editor->openFile(filename);
}
void undo() override {
std::cout << "关闭文件: " << filename << "\n";
}};
// 具体命令:保存文件 class S*eFileCommand : public Command { private: TextEditor* editor;
public: S*eFileCommand(TextEditor* e) : editor(e) {}
void execute() override {
editor->s*eFile();
}
void undo() override {
std::cout << "撤销保存操作\n";
}};
// 调用者:按钮或快捷键 class Button { private: Command* command;
public: void setCommand(Command* cmd) { command = cmd; }
void click() {
if (command) command->execute();
}};
支持撤销与历史记录
命令模式的强大之处在于能轻松实现撤销和重做。通过维护一个命令栈,每执行一个命令就压入栈中,撤销时弹出并调用undo()方法。
class CommandHistory {
private:
std::stack<Command*> history;
<p>public:
void push(Command* cmd) {
history.push(cmd);
}</p><pre class='brush:php;toolbar:false;'>void undo() {
if (!history.empty()) {
Command* cmd = history.top();
history.pop();
cmd->undo();
}
}};
使用方式:
int main() {
TextEditor editor;
CommandHistory history;
<pre class='brush:php;toolbar:false;'>OpenFileCommand openCmd(&editor, "main.cpp");
S*eFileCommand s*eCmd(&editor);
Button openBtn, s*eBtn;
openBtn.setCommand(&openCmd);
s*eBtn.setCommand(&s*eCmd);
openBtn.click(); // 执行:打开文件
s*eBtn.click(); // 执行:保存文件
history.push(&openCmd);
history.push(&s*eCmd);
history.undo(); // 撤销保存
history.undo(); // 撤销打开
return 0;}
优点与适用场景
使用命令模式带来的好处:
- 解耦发送者与接收者:调用者无需知道具体执行细节
- 支持撤销/重做:只需在命令对象中实现undo()方法
- 可扩展性强:新增命令无需修改现有代码
- 支持宏命令:可将多个命令组合成一个复合命令
- 可用于任务队列:命令可被序列化、延迟执行或跨线程执行
常见应用场景包括GUI按钮、菜单项、事务系统、操作日志、远程方法调用等。
基本上就这些。命令模式通过把“动作”变成对象,让程序结构更灵活,也更容易支持复杂交互逻辑。关键是设计好命令接口和管理好生命周期,避免悬空指针问题。使用智能指针(如std::shared_ptr)可以进一步提升安全性。
以上就是C++如何实现一个命令模式_C++将请求封装成对象以实现解耦和可撤销操作的详细内容,更多请关注其它相关文章!
# 怎么做
# 河西区全域营销推广招聘
# seo优化推广问题
# 外贸网站推广二次开发
# 赤峰租房网站建设
# 朝阳seo优化哪家好
# 宝山区网站建设推荐
# 雨湖区专业网站建设
# 考拉seo文章裂变
# 网络营销推广的转化率高
# 永州抖音付费营销推广
# 配置文件
# 绑定
# 解决方法
# c++
# 重写
# 保存文件
# 调用者
# 如何实现
# 有什么
# 重做
# red
# stream
# ios
# ai
# 栈
# 命令模式
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
58动漫网在线官方网 58动漫网正版动漫入口网址
Win11怎么设置鼠标主按键_Win11鼠标左右键功能互换
Composer的 "licenses" 命令如何帮助你遵守开源协议_检查项目依赖的许可证合规性
word邮件合并后日期格式不对怎么改_Word邮件合并日期格式修改方法
b站怎么看视频的弹幕数量_b站弹幕数量查看方法
如何使用纯J*aScript判断Input元素是否在特定类容器内
QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台
魅族20怎样在浏览器开无图省流_iPhone魅族20浏览器开无图省流【流量节省】
利用5118提升短视频内容效果_5118短视频关键词优化方法
消息称三星明年 2 月正式发布 HBM4,与 SK 海力士同台竞技
qq游戏手机版下载安装_qq游戏移动端入口
在VS Code中配置和运行Dart程序的完整步骤
J*aScript 字符串标签转换:使用正则表达式高效替换
Yandex浏览器官方网页版入口 Yandex浏览器最新版官网
网站内容防复制粘贴的实现策略与局限性
必由学官网快捷入口 必由学网页版在线学习平台
PHP中高效并行检查多链接状态的教程
C++如何生成随机数_C++ random库使用方法与范围设置
聚水潭ERP登录页面入口 聚水潭ERP官网登录界面
汽车之家官方网站官网入口_汽车之家网页版直接进入
如何提高微信支付的安全性_微信支付安全防护与设置建议
妖精漫画网页版登录入口免费_妖精漫画官网主页直接阅读漫画
优化大型XML文件解析:基于Python流式处理的内存高效方案
Lar*el用户头像管理:实现图片缩放、存储与旧文件安全删除的最佳实践
Python异步编程实践:使用Binance API构建实时交易数据流
蛙漫安全无毒 官方认证的绿色入口
解决Python单元测试中Mock异常方法调用计数为零的问题
高德地图沿途添加点失败如何解决 高德多点规划方法
Descript怎样用AI剪辑自动去噪_Descript用AI剪辑自动去噪【自动降噪】
初次安装JDK时环境变量如何正确配置_J*A_HOME与PATH设置规则讲解
一加手机拍照效果不好怎么办 一加哈苏影像调校与专业模式使用教程【高手篇】
Go语言中对Map值调用带指针接收者方法:原理与最佳实践
漫蛙漫画官方首页 漫蛙2漫画在线阅读入口
qq音乐在线播放入口_qq音乐电脑版登录链接
支付宝碰一碰设备是REDMI手机吗 博主拆机辟谣:处理器、内存都不一样
神庙逃亡小游戏在线玩 神庙逃亡小游戏入口
如何优雅地扩展SprykerGlue后端API授权逻辑,使用spryker/glue-backend-api-application-authorization-connector-extension
J*a中实现Go语言select通道多路复用机制
拼多多赚钱渠道_拼多多收益来源
AO3网页版合集入口 Archive of Our Own同人作品浏览指南
Composer如何解决json扩展缺失的错误
中兴Axon42Ultra怎样在文件App筛图_iPhone中兴Axon42Ultra文件App筛图【图片筛选】
163邮箱注册官网 免费申请163个人邮箱
纯CSS与HTML网格布局的HTML精简策略:SVG与JS方案解析
品牌机怎么重装系统 联想/戴尔/惠普笔记本恢复出厂系统教程
在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案
sublime怎么进行远程开发编辑_配置rsub/rmate实现sublime编辑服务器文件
KFC套餐升级怎么获取优惠代码_KFC套餐升级活动与优惠代码获取方法
mysql通配符支持数字匹配吗_mysql通配符能否用于数字匹配的解析
《燕云十六声》两周内达九百万玩家!位居畅销榜第五


2025-11-23
浏览次数:次
返回列表
:cout << "打开文件: " << filename << "\n";
}</p><pre class='brush:php;toolbar:false;'>void s*eFile() {
std::cout << "保存当前文件\n";
}