Java 枚举类适合构建状态机,通过抽象方法强制各状态实现行为、上下文解耦、字段预置元信息、组合策略模式分离复杂逻辑,提升可维护性与扩展性。

枚举类(Enum)本身是常量集合,但 Java 的 enum 支持定义字段、构造方法、抽象方法和具体方法,这使其天然适合表达“有固定状态 + 各状态有专属行为”的状态机场景。关键不是把状态机逻辑全塞进 enum,而是让 enum 承担“状态定义 + 行为分发”的职责,再结合策略或委托实现可维护的业务逻辑。
用抽象方法强制每个状态实现自己的行为
在 enum 中声明抽象方法(如 handle(Event event)),每个枚举常量在初始化时提供具体实现。这样编译期就能保证所有状态都覆盖了核心行为,避免漏写或运行时 switch 遗漏分支。
例如订单状态机:
(Java 示例)public enum OrderStatus {
CREATED {
@Override
public void handle(OrderContext ctx) {
if (ctx.isValidPayment()) {
ctx.transitionTo(PAID);
} else {
throw new IllegalStateException("Payment required");
}
}
},
PAID {
@Override
public void handle(OrderContext ctx) {
ctx.ship();
ctx.transitionTo(SHIPPED);
}
},
SHIPPED {
@Override
public void handle(OrderContext ctx) {
ctx.markAsDelivered();
ctx.transitionTo(DELIVERED);
}
};
public abstract void handle(OrderContext ctx);
}
将状态变更与上下文解耦,避免 enum 膨胀
enum 不应直接操作业务数据或持有状态引用。推荐引入一个轻量级上下文类(如 OrderContext),封装当前状态、数据、状态变更方法(transitionTo())等。enum 只负责“告诉上下文下一步做什么”,不负责“怎么存/怎么查/怎么校验”。
好处:
- enum 保持纯净,只表达状态语义和决策逻辑
- 上下文可被单元测试、支持事务、集成日志/监控
- 新增状态只需加 enum 常量 + 实现抽象方法,无需改其他类
用字段+构造器预置状态元信息,支撑通用处理
除了行为,很多状态机还需元数据:是否终态、允许的前驱状态、超时时间、对应事件类型等。可在 enum 中定义私有字段,在构造器中初始化:
public enum OrderStatus {
CREATED(Set.of(), Set.of("PAY"), 0),
PAID(Set.of("CREATED"), Set.of("SHIP"), 300), // 300秒自动关单
SHIPPED(Set.of("PAID"), Set.of("DELIVER"), 86400);
private final Set<String> allowedFrom;
private final Set<String> allowedEvents;
private final int timeoutSeconds;
OrderStatus(Set<String> allowedFrom, Set<String> allowedEvents, int timeoutSeconds) {
this.allowedFrom = Collections.unmodifiableSet(allowedFrom);
this.allowedEvents = Collections.unmodifiableSet(allowedEvents);
this.timeoutSeconds = timeoutSeconds;
}
// 提供安全访问方法
public boolean canEnterFrom(OrderStatus prev) {
return allowedFrom.isEmpty() || allowedFrom.contains(prev.name());
}
}
这类信息可被统一的状态校验器、定时任务、API 权限检查复用,避免重复硬编码。
必要时组合策略模式,分离复杂行为
如果某个状态的行为特别重(如调用多个服务、含分支流程、需注入依赖),不要在 enum 方法里写满业务代码。可让 enum 持有一个策略接口实例(如 OrderHandler),通过构造器注入 Spring Bean 或工厂创建:
public enum OrderStatus {
PAID(new PaymentOrderHandler()),
SHIPPED(new LogisticsOrderHandler());
private final OrderHandler handler;
OrderStatus(OrderHandler handler) {
this.handler = handler;
}
public void handle(OrderContext ctx) {
handler.execute(ctx);
}
}
这样 enum 仍是状态中枢,而具体实现交由独立类管理,利于测试、复用和团队协作。

















