游戏常见设计模式
游戏常见设计模式
时间:2026/04/09
关键词:单例、状态模式、命令模式、观察者、组件化、对象池
核心目标:从游戏开发常见场景出发,理解哪些模式真的有用,以及哪些模式容易被滥用。
1. 游戏代码为什么特别容易模式化
游戏逻辑常见特点:
- 实体多
- 状态多
- 事件多
- 生命周期复杂
- 性能敏感
因此很多经典模式在游戏里非常常见,但也特别容易被滥用。
2. 单例模式:能用,但要克制
单例通常用于:
- 配置中心
- 日志系统
- 全局资源管理器
最简单安全的写法通常是局部静态:
1 | class GameConfig { |
优点:
- 简单
- 线程安全初始化
缺点:
- 全局依赖隐蔽
- 测试困难
- 生命周期难拆
所以经验上:
- 单例适合少量基础设施,不适合把一切都做成全局对象
3. 状态模式:替代大 switch
当一个角色会在多种状态之间切换,例如:
- Idle
- Chase
- Attack
- Dead
如果全写在一个大 switch 里,代码会越来越乱。
状态模式的思路是:
- 每个状态自己负责更新逻辑和转移条件
1 | struct Monster; |
这样“状态行为”会比“状态枚举 + 大分支”更容易扩展。
4. 命令模式:把输入和行为解耦
适用场景:
- 输入映射
- 回放系统
- AI 行为排队
- 网络同步操作记录
基本思路:
- 把“做什么”封装成命令对象
1 | struct Command { |
这样可以做到:
- 排队执行
- 延迟执行
- 撤销/重放
5. 观察者 / 事件模式
适合:
- UI 更新
- 成就系统
- 音效触发
- 状态广播
思路是:
- 某个系统发事件
- 多个订阅者响应
优点:
- 降低模块直接耦合
风险:
- 调用链变隐蔽
- 调试困难
所以事件系统要控制好:
- 事件粒度
- 生命周期
- 订阅关系
6. 组件化 / ECS 思路
传统继承层级:
Monster -> BossMonster -> FlyingBossMonster -> ...
很容易爆炸。
组件化更偏向:
- Position
- Render
- Physics
- Health
通过组合形成实体能力。
这样更灵活,也更适合:
- 数据驱动
- 批量更新
- SoA / cache 友好设计
7. 对象池:减少频繁分配
游戏里这些对象往往高频创建销毁:
- 子弹
- 粒子
- 临时特效
如果每次都 new/delete,可能带来:
- 分配开销
- 碎片
- 抖动
对象池的思路是:
- 提前分配一批对象
- 使用时取出
- 用完后归还
但要注意:
- 池化会增加状态管理复杂度
- 不是所有对象都值得池化
8. 模板方法模式
适用于:
- 主流程固定
- 个别步骤由派生类决定
例如角色更新:
1 | struct Character { |
这种模式的优点是流程稳定,但要避免基类职责过重。
9. 游戏开发里最常见的误区
9.1 什么都做成单例
最后会形成巨型全局依赖网。
9.2 继承层级过深
很多时候组合比继承更稳。
9.3 事件系统滥用
会让控制流难以追踪。
9.4 为了模式而模式
很多小项目只需要清晰结构,不需要把所有经典模式全搬进来。
10. 一页总结
游戏里真正常用、且值得优先掌握的几个模式是:
- 状态模式
- 命令模式
- 观察者 / 事件模式
- 组件化 / ECS
- 对象池
单例不是不能用,但一定要克制。
如果只记一句:
游戏模式的价值不在“名词多高级”,而在于它能不能降低复杂状态和高频对象管理的混乱度。