2026/2/25 6:12:08
网站建设
项目流程
平阳网站建设公司,做网站成本,跨境外贸网,vps网站如何设置缓存设计模式[14]——命令模式#xff08;Command#xff09;一分钟彻底说透#xff08;C版软件领域真实例子#xff09;
一句话定义
将“请求”#xff08;操作#xff09;封装成一个独立的对象#xff0c;从而让发送者和执行者完全解耦#xff0c;支持撤销、重做、队列、…设计模式[14]——命令模式Command一分钟彻底说透C版·软件领域真实例子一句话定义将“请求”操作封装成一个独立的对象从而让发送者和执行者完全解耦支持撤销、重做、队列、日志等高级功能。最狠的比喻软件人专属图形编辑器如Photoshop/GIMP的“撤销/重做”每按一次“调亮度”“画笔”“裁剪”都生成一个命令对象放进历史栈 → 按CtrlZ就弹出上一个命令执行undo()客户端菜单/快捷键只知道“执行命令”完全不知道具体怎么调亮度为什么需要它坏味道瞬间爆炸不用命令模式你会直接这样写editor.brighten();// 菜单直接调用编辑器方法editor.crop();// 想加撤销每个操作都要在编辑器里写undo逻辑耦合到死// 想队列批量执行想记录操作日志想宏命令全寄和之前模式彻底分清10秒表项目责任链Chain of Responsibility装饰器Decorator命令Command核心意图请求沿链找处理者动态叠加行为将操作封装成对象支持撤销/队列关键元素next指针 可中断包装链 全执行execute() undo()执行时机立即沿链传递立即层层执行可延迟、可队列、可撤销典型场景Web中间件、事件过滤流加密/日志编辑器撤销、事务、宏命令、线程池口号“传下去直到有人接”“层层叠加”“命令即对象想干啥都行”真实软件例子图形编辑器撤销/重做系统#includeiostream#includememory#includevector#includestringusingnamespacestd;// 1. 接收者真正干活的对象classImageEditor{string state原始图片;public:voidbrighten(){state → 调亮;cout[Editor] 执行调亮 → 当前状态: stateendl;}voidcrop(){state → 裁剪;cout[Editor] 执行裁剪 → 当前状态: stateendl;}voidunbrighten(){/* 实际项目里恢复状态 */cout[Editor] 撤销调亮\n;}voiduncrop(){cout[Editor] 撤销裁剪\n;}voidshow()const{cout当前图片状态: stateendl;}};// 2. 命令接口classCommand{public:virtual~Command()default;virtualvoidexecute()0;virtualvoidundo()0;};// 3. 具体命令绑定接收者 操作classBrightenCommand:publicCommand{ImageEditor*editor;public:explicitBrightenCommand(ImageEditor*e):editor(e){}voidexecute()override{editor-brighten();}voidundo()override{editor-unbrighten();}};classCropCommand:publicCommand{ImageEditor*editor;public:explicitCropCommand(ImageEditor*e):editor(e){}voidexecute()override{editor-crop();}voidundo()override{editor-uncrop();}};// 4. 调用者维护命令历史栈classCommandHistory{vectorunique_ptrCommandhistory;ImageEditoreditor;public:explicitCommandHistory(ImageEditore):editor(e){}voidexecuteCommand(unique_ptrCommandcmd){cmd-execute();history.push_back(move(cmd));// 入栈}voidundo(){if(!history.empty()){history.back()-undo();history.pop_back();}else{cout无操作可撤销\n;}}voidshowState()const{editor.show();}};客户端撤销重做爽到飞起intmain(){ImageEditor editor;CommandHistoryhistory(editor);// 用户操作history.executeCommand(make_uniqueBrightenCommand(editor));history.executeCommand(make_uniqueCropCommand(editor));history.executeCommand(make_uniqueBrightenCommand(editor));history.showState();// 原始图片 → 调亮 → 裁剪 → 调亮cout\n 用户按 CtrlZ 撤销 \n;history.undo();// 撤销最后一次调亮history.undo();// 撤销裁剪history.showState();// 回到只调亮一次的状态}输出[Editor] 执行调亮 → 当前状态: 原始图片 → 调亮 [Editor] 执行裁剪 → 当前状态: 原始图片 → 调亮 → 裁剪 [Editor] 执行调亮 → 当前状态: 原始图片 → 调亮 → 裁剪 → 调亮 当前图片状态: 原始图片 → 调亮 → 裁剪 → 调亮 用户按 CtrlZ 撤销 [Editor] 撤销调亮 [Editor] 撤销裁剪 当前图片状态: 原始图片 → 调亮C 真实项目里无处不在GUI框架Qt的QUndoCommand编辑器、场景编辑器游戏编辑器Unreal Editor的Transaction系统事务管理数据库事务Commit/Rollback线程池/任务队列把Command放进队列异步执行宏命令组合多个Command成一个“超级命令”如“保存项目” 保存文件 清理缓存 记录日志终极口诀编辑器开发者专属“操作封装成对象撤销重做随便搞菜单快捷键解耦历史栈里随便跳”刻在DNA里的一句话当你需要“支持撤销/重做、延迟执行、队列操作、日志记录”等高级行为且不想让调用者和具体操作耦合时立刻上命令模式——把“要做什么”封装成对象想怎么玩都行现在命令模式彻底说透了下一期是解释器模式Interpreter[15]虽然是GoF里最冷门的但也有真实用途。