状态机模式的核心是将状态转换的合法性校验与行为执行封装在状态类或状态机内部,禁止外部直接修改状态;每个状态实现统一接口并自主决定能否转换及执行后续动作;通过状态机类提供唯一高阶入口方法,统一管理上下文、日志、事务等;轻量场景可用枚举+策略映射替代硬编码;状态对象应通过工厂或builder创建,确保不可变性与构造安全。

在状态机模式中,Java 封装的核心是把“某个状态能否转到另一个状态”以及“转换时要做什么”这两件事,从外部调用者手里收回来,藏进状态对象或状态机内部,不让业务代码随意 new 状态、手动赋值 state 字段、绕过校验直接跳转。
用状态类封装转换合法性与行为
每个状态(如 Draft、Published、Archived)定义为独立类,实现统一接口(如 State),接口中声明 handleEvent() 或 transitionTo() 方法。关键点在于:状态类自己决定“能不能转”,也负责执行转换后的动作。
- 不暴露 setState() 这类 setter,避免外部强行修改
- 每个状态类的 transitionTo(NextState) 方法里写明前置条件(如 “只有当前是 Draft 才能 publish”),不满足就抛异常或返回失败结果
- 转换成功后,可触发副作用:更新时间戳、发通知、持久化等,这些逻辑随状态走,不散落在 service 层
用状态机类封装转换入口与上下文管理
引入一个 StateMachine 类作为唯一入口,持有当前状态引用和业务上下文(如订单、文档实体)。它不暴露状态字段,只提供高阶方法如 publish()、archive()。
- 这些方法内部调用当前状态的 canPublish() + doPublish(context),把判断和执行合在一处
- 状态变更由状态机自己完成:旧状态返回新状态实例,状态机更新引用(推荐不可变状态对象)
- 所有转换都经过同一入口,便于统一加日志、事务、审计或熔断
用枚举+策略映射替代硬编码 if-else
如果不想为每个状态建类(轻量场景),可用 enum 表示状态值,再配合 Map
- 定义 StateTransition 接口,含 isValid(Context) 和 execute(Context)
- 每个转移规则实现该接口,把业务校验(如库存是否充足)、副作用(扣减库存)全包进去
- 状态机调用 transitions.get(current).get(event).isValid(ctx),通过才执行
配合 Builder 或工厂隐藏构造细节
状态对象不应被随意 new 出来。可用静态工厂方法或 builder 控制创建路径:
- Draft.createFor(document) 可校验 document 是否为空、是否有必要字段
- 状态转换方法(如 draft.publish())返回 Published 实例,而不是 void —— 强制调用者接收新状态,体现不可变性
- 禁止 public 构造函数,用 package-private + 工厂组合,防止跨包乱造状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











