状态模式将对象行为按状态封装为独立类,通过委托当前状态实例实现行为切换,消除if-else判断。以订单为例,定义状态接口、实现各状态类、订单持有状态引用、状态切换由自身控制,使逻辑清晰、易扩展、防非法转移。

状态模式的核心思想
状态模式把对象在不同状态下的行为封装成独立的类,让对象内部状态改变时,其行为也随之改变。它不是用 if-else 判断当前状态再调用对应逻辑,而是让“状态本身”决定该做什么——对象只需委托给当前状态实例,完全解耦行为与条件判断。
典型 if-else 场景与问题
比如一个订单对象有“待支付”“已支付”“已发货”“已完成”“已取消”等状态,每个操作(如支付、发货、退款)都需要先检查当前状态是否允许,再执行动作,还要更新状态。硬编码会形成大量嵌套或并列的 if-else,难以维护、易出错、新增状态需修改多处。
常见写法的问题:
- 订单类膨胀,职责不单一,既管业务又管状态流转
- 状态校验和行为逻辑混在一起,阅读成本高
- 添加新状态(如“部分发货”)要改所有涉及状态判断的方法
- 状态非法转移难约束(比如从“已完成”又去“支付”)
用状态模式重构的关键步骤
以订单为例,分四步落地:
-
定义状态接口:声明所有状态共有的行为方法,如
pay()、ship()、cancel() -
为每种状态实现具体类:每个类只关注自己状态下的合法行为。例如
PaidState实现ship()(允许发货),但pay()抛异常或忽略 -
订单持有状态引用:用组合代替继承,订单持有一个
OrderState接口引用,初始设为CreatedState -
状态切换由状态自身控制:比如
CreatedState.pay()执行成功后,主动把订单的状态引用设为new PaidState(order)
这样,订单的 pay() 方法就简化为:currentState.pay(),无需任何 if-else。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
实际代码片段示意
状态接口:
interface OrderState {
void pay(Order order);
void ship(Order order);
void cancel(Order order);
}
具体状态之一(已支付状态):
class PaidState implements OrderState {
@Override
public void pay(Order order) {
throw new IllegalStateException("Already paid");
}
@Override
public void ship(Order order) {
System.out.println("Shipping...");
order.setState(new ShippedState(order)); // 自行切换状态
}
@Override
public void cancel(Order order) {
System.out.println("Cancelling paid order...");
order.setState(new CancelledState(order));
}
}
订单类(精简版):
class Order {
private OrderState state;
public Order() {
this.state = new CreatedState(this);
}
public void pay() { state.pay(this); }
public void ship() { state.ship(this); }
public void cancel() { state.cancel(this); }
public void setState(OrderState state) { this.state = state; }
}
状态类可持有对上下文(Order)的引用,用于读取数据或触发状态变更,但避免循环依赖。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










