跳转至

设计模式与代码组织

这一页不是为了“背设计模式名词”,而是为了帮你看懂本项目为什么长这样。

你在代码里最常看到的几个模式

单例 Singleton

本项目里大量核心模块都是单例,例如:

  • VisionModule::Instance()
  • TaskMediator::Instance()
  • SystemRunner::Instance()
  • Python 侧经由 CppPackage 暴露出的 WorldModel.Instance()DebugEngine.Instance()

这样做的原因通常是:

  • 这些对象代表“系统里唯一的一份全局状态”
  • 创建和同步成本高,不适合到处 new
  • 大量模块都需要访问它们

但单例也意味着:

  • 你修改全局状态时要格外小心副作用
  • 调试时要搞清楚“这是局部变量”还是“改了整个系统都受影响”

工厂 Factory

典型代表是 TaskFactoryV2PlayerRole::makeIt... 系列函数。

思路是:

  • 外部先描述“我要一个什么任务”
  • 工厂负责把这个描述包装成真正的 CPlayerTask

这样高层代码不用关心每个 Skill 的构造细节,只需要关心“我要什么能力”。

中介者 Mediator

典型代表是 TaskMediator

它负责:

  • 按车号保存当前周期各个机器人任务
  • 保存一些角色标签,例如 goalie / back / marking
  • DecisionModule、Skill、运动控制等模块通过统一入口交换任务信息

你可以把它理解成“本周期任务分发表 + 角色标记中心”。

状态机 State Machine

Python 顶层的大量 Play 都是状态机,例如:

  • NormalPlayMessi_11vs11_new
  • GameStop

状态机的好处是:

  • 战术逻辑按状态拆开更清晰
  • 每一帧只关心“当前状态做什么、何时跳转”
  • 比起把全部逻辑塞在一个大函数里,调试体验会好很多

在本项目里,模式服务于什么目标

不要把模式理解成“为了显得高级”。它们解决的是很具体的问题:

  • 单例:共享全局运行时状态
  • 工厂:统一创建任务对象
  • 中介者:降低模块之间的直接耦合
  • 状态机:组织高层战术流程

新人最值得养成的习惯

当你看到一个新类时,先问自己三个问题:

  1. 它是“状态中心”还是“纯工具”?
  2. 它是“高层调度”还是“底层执行”?
  3. 它应该被直接依赖,还是应该通过工厂 / 中介者访问?

如果这三个问题想清楚了,读源码会顺很多。