设计模式 —— 命令模式
Table of Contents
1 什么是命令模式
"将请求封装成对象,从而允许对象经过队列、允许日志打印、支持撤销和恢复。 " —— 这就是命令模式的全部内容。
如果用 UML 表示的话。。。(翻了半天找不到UML的书)
算了,我受够这些繁文缛节了:
using ExecFn = function<void()>; using CancelFn = function<void()>; void runCommand(ExecFn exec, CancelFn cancel);
简单地说,把要执行的请求,(可能还有取消请求)当作对象传输,就是命令模式。比如 std::for_each()
就是命令模式。
“撤销” 是我最喜欢命令模式的地方,文本编辑器里面使用 “Ctrl-Z Z Z Z Z Z”就很适合用命令模式的撤销功能。
2 命令模式的用途
因为命令是一个对象,就可以将命令存储到队列、或者数据库中、或者在网络中传输。
我们可以在网络中传输命令对象,实现格斗游戏。玩家A按下攻击按钮,将攻击命令封装成对象,通过网络传输给玩家B,在玩家B的游戏界面上,玩家A的角色执行攻击命令:
在游戏中加入 AI 也会更加方便:
命令模式的 “撤销” 功能,让格斗游戏中的 “rollback netcode” 实现更加简单。网络存在延迟,所以本地游戏界面先渲染本地命令执行的结果,等到网络将对手的命令发送过来,再 rollback 到对手命令发送之前,综合本地和网络命令后再显示渲染结果,这样格斗游戏就不会因为网络延迟显得太卡。
3 总结
命令模式的核心是用“对象”表示“命令”,而“对象”在现代可以是结构体、类对象、函数、lambda 表达式等。在需要撤销,或者需要将命令与表现解耦时,常常使用命令模式。