这个题目非常赞!😎 很多同学写 Java 程序时,业务逻辑一复杂,if-else
嵌套就会像“意大利面”一样,难以维护。这时候 状态机(State Machine) 就能登场,用清晰的状态转移表,把复杂逻辑优雅地组织起来。
我帮你写一个详细的讲解思路,分成原理 + 三种常见实现方式 + 示例。
Java 状态机详解 —— 三种状态机实现方式优雅消灭 if-else 嵌套
1. 什么是状态机?
状态机(State Machine)是一种编程思想,用来处理状态切换和事件驱动的问题。
核心要点:
- 有限状态:系统只能处于有限的几种状态(例如:
待支付
、已支付
、已发货
)。 - 事件触发:外部事件触发状态转移(如:用户付款 -> 状态从“待支付”到“已支付”)。
- 转移规则:定义清晰的状态转移关系,避免大量 if-else 嵌套。
举个例子:订单系统状态机
待支付 --(支付成功)--> 已支付 --(发货)--> 已发货
2. 传统 if-else 的痛点
if (status.equals("待支付")) {
if (event.equals("支付成功")) {
status = "已支付";
} else {
throw new IllegalStateException("非法操作");
}
} else if (status.equals("已支付")) {
if (event.equals("发货")) {
status = "已发货";
}
} else {
...
}
👉 随着状态增多,代码臃肿,扩展性差。
3. 三种状态机的优雅实现方式
方式一:枚举 + 映射表(简单直观)
通过 Map<状态, Map<事件, 新状态>>
记录状态转移表。
import java.util.*;
enum State { WAIT_PAY, PAID, SHIPPED }
enum Event { PAY, SHIP }
public class EnumStateMachine {
private static final Map<State, Map<Event, State>> transitions = new HashMap<>();
static {
transitions.put(State.WAIT_PAY, Map.of(Event.PAY, State.PAID));
transitions.put(State.PAID, Map.of(Event.SHIP, State.SHIPPED));
}
private State currentState = State.WAIT_PAY;
public void fire(Event event) {
Map<Event, State> map = transitions.get(currentState);
if (map != null && map.containsKey(event)) {
currentState = map.get(event);
System.out.println("转移成功 -> 当前状态: " + currentState);
} else {
throw new IllegalStateException("非法事件: " + event + " 在状态: " + currentState);
}
}
public static void main(String[] args) {
EnumStateMachine sm = new EnumStateMachine();
sm.fire(Event.PAY);
sm.fire(Event.SHIP);
}
}
✅ 优点:简洁明了,适合中小型业务。
方式二:状态模式(面向对象,扩展性强)
通过 State 接口 + 具体状态类,把状态转移逻辑封装到对象里。
interface State {
void handle(Event event, Context ctx);
}
class WaitPay implements State {
public void handle(Event event, Context ctx) {
if (event == Event.PAY) {
ctx.setState(new Paid());
System.out.println("支付成功 -> 已支付");
} else {
throw new IllegalStateException("非法事件");
}
}
}
class Paid implements State {
public void handle(Event event, Context ctx) {
if (event == Event.SHIP) {
ctx.setState(new Shipped());
System.out.println("已发货");
}
}
}
class Shipped implements State {
public void handle(Event event, Context ctx) {
System.out.println("订单已完成");
}
}
class Context {
private State state = new WaitPay();
public void setState(State state) { this.state = state; }
public void fire(Event event) { state.handle(event, this); }
}
✅ 优点:高扩展性,符合 OOP 思想;
❌ 缺点:类数量多,结构偏重。
方式三:借助第三方库(高效 + 工程化)
例如 Spring Statemachine 或 Squirrel。
Spring Statemachine 配置示例:
@Configuration
@EnableStateMachine
public class StateMachineConfig extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
states.withStates()
.initial("WAIT_PAY")
.state("PAID")
.state("SHIPPED");
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
transitions
.withExternal().source("WAIT_PAY").target("PAID").event("PAY")
.and()
.withExternal().source("PAID").target("SHIPPED").event("SHIP");
}
}
✅ 优点:适合大型复杂系统,支持持久化、并发、安全控制;
❌ 缺点:学习成本高,配置略繁琐。
4. 总结
- 枚举 + Map:简单实用,适合中小型项目;
- 状态模式:面向对象,逻辑清晰,扩展性好;
- 框架方案:工业级解决方案,适合复杂业务流程;
通过状态机,Java 开发可以彻底摆脱 if-else
的泥潭,让业务逻辑更加清晰、优雅、可维护。
发表回复