# FiniteStateMachine.py 技术文档 本文档描述了 `FiniteStateMachine.py` 模块的设计与使用方式,该模块实现了一个轻量级的有限状态机(Finite State Machine, FSM)系统,适用于需要状态驱动行为的对象管理。 --- ## 1. 概述 本模块提供了一套基于类的有限状态机框架,包含以下核心组件: - `BaseFSM`: 所有具体状态类的抽象基类。 - `FSMManager`: 状态管理器,用于注册和调度不同状态的行为逻辑。 - `FSMObject`: 支持状态切换的游戏或业务对象基类。 该设计采用**状态模式**(State Pattern),将状态的行为封装在独立的状态对象中,并通过管理器统一调度。 --- ## 2. 核心类说明 ### 2.1 `BaseFSM` —— 状态行为抽象基类 `BaseFSM` 是所有具体状态类必须继承的抽象基类。它定义了状态的三个生命周期方法。 #### 方法接口 | 方法 | 描述 | |------|------| | `enterState(obj)` | 当对象进入此状态时调用。通常用于初始化操作。 | | `execState(obj)` | 在每帧或每次更新周期中执行当前状态的逻辑。 | | `exitState(obj)` | 当对象退出此状态前调用。可用于清理资源或保存状态数据。 | > ⚠️ 注意:这三个方法均为抽象方法,子类必须重写,否则会抛出 `NotImplementedError`。 #### 示例子类定义(用户需自行实现) ```python class IdleState(BaseFSM): def enterState(self, obj): print(f"{obj} 进入空闲状态") def execState(self, obj): print(f"{obj} 正处于空闲状态") def exitState(self, obj): print(f"{obj} 离开空闲状态") ``` --- ### 2.2 `FSMManager` —— 有限状态机管理器 全局唯一的状态管理器,负责维护状态与其对应 FSM 实例之间的映射关系,并驱动状态更新流程。 #### 属性 - `_fsms` (`dict`):内部字典,键为状态标识(如字符串),值为对应的 `BaseFSM` 子类实例。 #### 构造函数 ```python def __init__(self) ``` 初始化一个空的状态映射表。 #### 公共方法 | 方法 | 参数 | 返回值 | 描述 | |------|------|--------|------| | `addState(state, fsm)` | `state`: str 或 hashable
`fsm`: BaseFSM 实例 | 无 | 将指定状态名绑定到一个 FSM 实例上。 | | `delState(state)` | `state`: 要删除的状态名 | 无 | 移除指定状态及其 FSM 实例。若状态不存在则引发 KeyError。 | | `getFSM(state)` | `state`: 查询的状态名 | BaseFSM 实例 | 获取与状态名关联的 FSM 对象。若未注册则引发 KeyError。 | | `frame(objs, state)` | `objs`: 可迭代的 FSMObject 列表
`state`: 当前期望状态 | 无 | 遍历对象列表,根据其当前状态决定是否切换或保持状态。 | #### `frame()` 方法逻辑详解 ```python def frame(self, objs, state): for obj in objs: if state == obj.curr_state: obj.keepState() else: obj.changeState(state, self._fsms[state]) ``` - 若对象当前状态等于目标状态 → 调用 `keepState()` 继续执行当前状态逻辑。 - 否则 → 调用 `changeState()` 切换至新状态,并加载对应 FSM 行为。 > ✅ 推荐用法:每一游戏/逻辑帧调用一次 `manager.frame(objects, current_global_state)` 来同步所有对象的状态行为。 --- ### 2.3 `FSMObject` —— 支持状态机的对象基类 表示可以拥有有限状态机行为的实体对象(例如游戏角色、UI 控件等)。 #### 属性 | 属性 | 类型 | 描述 | |------|------|------| | `fsm_cur_state` | hashable (e.g., str) | 当前所处的状态标识。 | | `fsm_state_object` | BaseFSM 实例 | 当前状态对应的行为控制器。 | #### 方法 | 方法 | 参数 | 返回值 | 描述 | |------|------|--------|------| | `attachFSM(state, fsm)` | `state`: 初始状态名
`fsm`: BaseFSM 实例 | 无 | 初始化对象的状态机,设置初始状态及行为逻辑。 | | `changeState(new_state, newfsm)` | `new_state`: 新状态名
`newfsm`: 新状态对应的 FSM 实例 | 无 | 执行完整的状态切换流程:
1. 调用旧状态的 `exitState`
2. 更新状态和 FSM 实例
3. 调用新状态的 `enterState` 和 `execState` | | `keepState()` | 无 | 无 | 维持当前状态,仅执行当前 FSM 的 `execState(self)` 方法。 | > 🔁 **注意**:`changeState` 中存在变量名拼写错误:`new_fsm` 应为 `newfsm`(见下文“已知问题”)。 --- ## 3. 使用示例 ```python # 定义两个状态 class WalkingState(BaseFSM): def enterState(self, obj): print("开始行走") def execState(self, obj): print("正在行走...") def exitState(self, obj): print("停止行走") class JumpingState(BaseFSM): def enterState(self, obj): print("起跳!") def execState(self, obj): print("空中飞行...") def exitState(self, obj): print("落地") # 创建管理器并注册状态 manager = FSMManager() manager.addState("walk", WalkingState()) manager.addState("jump", JumpingState()) # 创建对象并附加初始状态 player = FSMObject() player.attachFSM("walk", WalkingState()) # 模拟运行帧 objects = [player] manager.frame(objects, "jump") # 切换到跳跃状态 manager.frame(objects, "jump") # 保持跳跃状态 manager.frame(objects, "walk") # 切回行走状态 ``` **输出结果:** ``` 开始行走 正在行走... 起跳! 空中飞行... 落地 开始行走 正在行走... ``` --- ## 4. 已知问题与改进建议 ### ❌ Bug: 变量名拼写错误 在 `FSMObject.changeState()` 方法中: ```python self.fsm_state_object = new_fsm # 错误:应为 newfsm ``` ✅ 正确写法应为: ```python self.fsm_state_object = newfsm ``` 建议修复如下: ```python def changeState(self, new_state, newfsm): self.fsm_state_object.exitState(self) self.fsm_cur_state = new_state self.fsm_state_object = newfsm self.fsm_state_object.enterState(self) self.fsm_state_object.execState(self) ``` ### 🛠 建议改进 | 改进点 | 说明 | |-------|------| | 添加异常处理 | 在 `getFSM()` 和 `delState()` 中加入 `KeyError` 捕获并友好提示。 | | 支持状态栈(Push/Pop) | 可扩展支持暂停当前状态、临时进入另一个状态后再返回。 | | 引入状态转换条件 | 当前由外部控制切换,可引入 `canEnter()` 方法判断是否允许进入某状态。 | | 使用枚举作为状态类型 | 提高类型安全性,避免字符串硬编码错误。 | --- ## 5. 总结 `FiniteStateMachine.py` 提供了一个简洁、可扩展的状态机基础架构,适合用于: - 游戏开发中的角色行为控制 - UI 状态流转管理 - 机器人动作序列控制 - 任何需要清晰状态划分的系统 通过组合 `BaseFSM` 子类、`FSMManager` 和 `FSMObject`,开发者可以轻松构建模块化、易维护的状态驱动程序。 --- 📌 **版本信息** - 文件名: `FiniteStateMachine.py` - 设计模式: 状态模式(State Pattern) - 适用范围: Python 3.x