Java状态机核心是将状态切换显式建模为一等公民,用enum定义状态/事件,转移表声明转换规则,上下文统一管控fire入口,强制校验与日志追溯,并支持回滚与权限钩子。

Java 中流程控制设计状态机逻辑,核心是把“状态切换”从零散的 if-else 或 switch 拆出来,变成可配置、可追踪、可验证的结构。重点不在写多少代码,而在于让状态流转本身成为一等公民——谁在什么条件下能变成什么样,必须清晰、集中、不模糊。
用枚举定义状态和事件
状态和事件都用 enum 是最轻量也最安全的做法。它们天然不可变、线程安全、支持 switch(编译期检查),还能直接作为 map 的 key 或数据库字段存储。
- 状态枚举只列所有合法终态,比如 PENDING、PAID、SHIPPED、CANCELED
- 事件枚举对应触发动作,比如 PAY_SUCCESS、CANCEL_REQUEST、SHIP_CONFIRMED
- 避免用数字或字符串硬编码状态值,否则后期改名、加状态、查日志都会出错
用转移表明确转换规则
别把“从 A 支付成功变成 B”这种逻辑藏在 service 方法里。应该显式定义一个转移规则集合,例如:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 每个规则包含:当前状态 + 触发事件 + 目标状态 + 可选处理逻辑(比如扣库存、发消息)
- 运行时根据当前状态和输入事件,在表中查找唯一匹配项;没找到就抛异常,而不是静默失败
- 规则可以存在内存 List 中,也可以加载自数据库或 JSON 配置,方便运营调整而不发版
用上下文封装状态变更入口
对外只暴露一个 fire(Event event) 方法,内部完成校验、查表、执行 handler、更新状态、记录日志全套动作。
立即学习“Java免费学习笔记(深入)”;
- 上下文对象持有当前状态引用,并提供 setNextState() 方法统一更新
- 所有状态变更必须经过这个入口,杜绝直接赋值 status = PAID 这类绕过校验的操作
- 建议加上乐观锁版本号或状态变更时间戳,防止并发重复提交导致状态错乱
补上可追溯与可干预能力
真实业务中,光“能转”不够,还要知道“谁、什么时候、为什么转”。所以状态机不是黑盒,得留出口:
- 每次状态变更自动记录操作人、时间、事件类型、前状态、后状态、扩展原因字段
- 支持按需回滚(如审批驳回后回到上一状态),但需明确定义哪些状态允许退回、退到哪
- 对高危转换(如取消已发货订单)增加权限校验钩子,可插拔接入 RBAC 或审批流

















