命令模式如何解决命令/请求硬编码问题?基于《游戏编程模式》的问询
核心逻辑类比(JS开发者视角)
你可以把C++里的Command子类实例直接理解为JS中的无参函数引用:
- C++的
JumpCommand实例调用execute(),等价于JS中你定义的const jumpCmd = () => jump()执行jumpCmd() - InputHandler类里的
buttonX_/buttonY_这类指针,等价于JS里用于存储绑定函数的映射表:const buttonMap = { X: jumpCmd, Y: fireCmd, A: swapCmd, B: lurchCmd }
运行时绑定的具体实现
你猜测的用new初始化指针是对的,只需要给InputHandler补充绑定方法即可:
class InputHandler { public: void handleInput(); // 新增绑定方法 void bindCommand(int button, Command* command); private: Command* buttonX_; Command* buttonY_; Command* buttonA_; Command* buttonB_; }; void InputHandler::bindCommand(int button, Command* command) { switch (button) { case BUTTON_X: buttonX_ = command; break; case BUTTON_Y: buttonY_ = command; break; case BUTTON_A: buttonA_ = command; break; case BUTTON_B: buttonB_ = command; break; } }
当用户在设置界面修改按键绑定时,直接调用绑定方法即可,完全不需要修改handleInput的逻辑:
// 比如用户把跳跃动作从X键改到B键,只需要执行这一行 inputHandler->bindCommand(BUTTON_B, new JumpCommand());
实际开发中通常会提前创建所有动作的全局单例(比如Command* g_jump = new JumpCommand();),绑定时直接传单例指针即可,不需要重复创建实例,避免内存泄漏。
为什么不用运行时if/else实现同类效果
并不是完全不能实现,但是硬编码if/else的方案有两个致命问题:
- 维护成本极高:如果你要支持100种游戏动作,你需要在
handleInput里写100条if/else判断,每新增一个动作都要修改handleInput的代码,违反开闭原则。而用命令模式的话,新增动作只需要新增一个Command子类,绑定的时候传进去就行,handleInput的代码永远不需要修改。 - 扩展性差:命令模式的优势远不止动态绑定按键,后续你要实现撤销/重做、动作队列、录像回放等功能,只需要给Command类加对应的
undo()方法、把执行过的Command实例存下来即可,这些能力是硬编码if/else完全无法支持的。
内容的提问来源于stack exchange,提问作者user51462
相关产品推荐
相关产品推荐

