版权声明:未经作者允许不可转载 https://blog.csdn.net/qq_38134452/article/details/88660499
命令就是一个对象化(实例化)的方法调用(摘自《游戏编程模式》)
- 上述引用是将命令模式概念进行精简的版本,未精简的概念为:命令模式就是"将一个请求(request)封装成一个对象,从而允许你使用不同的请求、队列或日志将客户端参数化,同时支持请求操作的撤销与恢复" 。(你大概也不想理解这一句)
- 这两个概念与“回调(callback)”具有共性。
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。(摘自百度百科)
- 命令就是面向对象化的回调
理解
抛开上面的概念,我们去通过一些特定的情形去理解命令模式。在书中的第一个情景为游戏中的输入配置。在游戏开发中,游戏的输入模块可以简化成如下图:
体现命令模型就在于游戏逻辑之输入判定部分的设计上
- 简单的实现(硬编码)
void InputHandler : handeInput { if(is_press1) action1(); else if(is_press2) action2(); else if(……) …… }
- 缺陷:将输入输出与游戏动作绑定在了一起(我们无法动态修改 if 之后的事件)
- 为了支持自定义功能,我们要对直接调用进行“开刀”,因为直接调用是照成无法自定义的原因。游戏逻辑应该这样设计:
这就是命令模式。可替换的对象用来实现对多种输入事件的可修改。输入与事件之间不再是一个直接调用的关系,而是利用其他对象进行间接调用。
- 利用继承与虚函数实现
class Command { public: virtual ~Command() {} virtual void excute() = 0; } class Action1 : public Command { public: virtual void excute(){ action1(); } } class Action2 : public Command { public: virtual void excute(){ action2(); } } class InputHandler { public: void handleInput(); //写一些方法来对下列指针和键位进行绑定…… //基本方法是改变指针指向的对象(类型) private: Command* button_X; Command* button_Y; Command* button_Z; } void InputHandler::handleInput() { if(isPress_X) button_X->excute(); else if(isPress_Y) button_Y->excute(); else if(isPress_Z) button_Z->excute(); }
- 关于输入配置的进一步探索:解放固定的被操作角色(修改上述的代码)
lass Command { public: virtual ~Command() {} virtual void excute(GameActor& actor) = 0; } class Action1 : public Command { public: virtual void excute(GameActor& actor){ action1(); } } Command* InputHandler::handleInput() { if(isPress_X) return button_X; else if(isPress_Y) return button_Y; else if(isPress_Z) return button_Z; } //游戏逻辑中 Command* command = inputHandler.handleInput(); if(command) { command->excute(actor); }
- 上述的探索结果在游戏中人工智能中非常有意义。针对不同的角色执行不同的AI代码以达到不同的AI层级,这使得在游戏难度中具有更好的灵活度。
其他例子:撤销和重做
- 这里不再贴出书中的解析代码,只给出整个代码利用命令模式的思想体现:
- 撤销功能的要点在于:①记录前几步的对象属性②需要一个独立的选择对象来对其进行操作
- 前面的探索中,我们独立出了对象:引用参数(actor) —— 这记录了我们需要撤销的对象
- 新增部分:撤销时读取记录前一步的对象属性,用栈的数据结构特点可以很好的实现。
关于这一部分详细代码可以看原书
总结
-
命令模式极大程度上的避免了对灵活部分进行硬编码
-
基本思想方法是间接法。正如在两个人的交流中,为了避免产生冲突,两者之间需要一个可以调和的人,进行处理。
-
再一次给出联系图
-
命令模式的应用重点在于上图中可替换对象的设计。
知识点全部源于《Game Programming Patterns》,中文名《游戏编程模式》,图片来源于网络