状态模式通过将状态封装为对象来管理流程控制,核心是上下文委托具体状态类处理行为与切换,避免条件判断,提升可扩展性与可维护性。

用状态模式管理 Java 流程控制中的状态切换,核心是把“状态”从条件判断里抽出来,变成可替换的对象。它不靠 if-else 堆逻辑,而是让每个状态自己决定“能做什么、变成谁”。订单、订单审核、审批流、设备控制等流程类场景特别适合。
状态模式怎么组织流程逻辑
流程控制本质是一连串状态 + 转换规则。比如一个审批单:草稿 → 提交 → 审核中 → 通过/驳回 → 归档。状态模式把它拆成三部分:
- 上下文(Context):比如 ApprovalContext,只管持有一个当前状态对象,对外暴露 approve()、reject()、revoke() 这类统一方法,内部全委托给当前状态
- 状态接口(State):定义所有流程动作的签名,如 void approve(ApprovalContext ctx)、void reject(ApprovalContext ctx),不写实现
- 具体状态类:如 DraftState、SubmittedState、ApprovedState,每个只实现自己状态下合法的动作;比如 DraftState 的 approve() 会把 ctx.setState(new SubmittedState()),而 reject() 直接抛 UnsupportedOperationException
状态切换由状态自己驱动,不是上下文判断
关键区别在于:谁决定下一步?传统写法是上下文里写 if (status == DRAFT) { … },而状态模式里,这句逻辑被移到 DraftState 内部——它知道“我被 approve 后该变成 SubmittedState”。这样做的好处是:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 新增一个“加签中”状态,只需加一个 SignedState 类,不用改 ApprovalContext 或其他状态类
- 每个状态类职责单一,测试也容易:只测 DraftState 的 approve 行为,不关心 ApprovedState 怎么处理
- 非法操作天然被拦截:比如在 ApprovedState 调用 revoke(),直接抛异常或静默忽略,无需额外校验
避免用枚举驱动状态决策
别把状态枚举(如 enum OrderStatus { PENDING, PAID, SHIPPED })当主控逻辑。枚举适合做常量标识,但不适合承载行为。如果用 switch(status) { case PENDING: … },就又回到条件地狱。状态模式要求:状态即对象,行为即方法。枚举可以保留作日志、序列化或前端展示用,但流程执行必须走 State 接口实例。
注意状态间依赖和边界情况
真实流程常有约束,比如“已归档的单据不能撤回”“驳回后允许重新提交”。这些规则要明确写在对应状态类里,而不是堆在上下文里。另外建议:
- 状态切换前做必要校验(如权限、数据完整性),可在状态方法开头统一 check,失败则不换状态
- 支持状态回退时,别让每个状态都存“上一个状态”,而是用状态类组合或事件溯源更稳妥
- 如果流程分支多(如审核后可能跳转到财务、法务、运营多个环节),可用策略模式配合状态模式,把分支路由逻辑外置
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










