目录
[3、ArrayList 配置"状态流"](#3、ArrayList 配置“状态流”)
前言
关于Java的设计模式分类如下:

对于状态模式的组件组成,如下所示:

1、状态模式
1.1、介绍
允许一个对象在其内部状态发生改变时,行为也随之改变,看起来就像对象修改了它的类。
- 状态模式就是把"状态"封装成独立的类,不同状态下执行不同的逻辑
- 状态切换由对象自己控制,而不是外部用 if-else/switch来判断
1.2、设计背景
问题场景:
java
if (status == "UNPAID") { /* 处理支付 */ }
else if (status == "PAID") { /* 处理发货 */ }
else if (status == "SHIPPED") { /* 处理收货 */ }
- 每加一个状态,要修改这段代码
- 状态切换逻辑和行为混在一起,难维护
状态模式的好处:
- 把每个状态的逻辑单独放在一个类中
- 遵循 开闭原则(新增状态只加类,不改原来代码)
- 状态的切换由对象自身控制,不依赖外部复杂判断
两者对比,如下所示:

1.3、适用场景
在项目中常用的场景如下:
- Spring StateMachine(状态机框架)
- 订单系统:未支付 → 已支付 → 已发货 → 已完成
- 工作流引擎(Flowable、Activiti)
- Netty Channel 状态:UNREGISTERED → REGISTERED → ACTIVE → INACTIVE
💡 因此:
- 如果状态很少且不会变,可以用 if-else
- 如果状态多、变化频繁,并且有复杂行为 => 用状态模式
2、实现
2.1、if-else实现
java
public class Order {
public static final int UNPAID = 0;
public static final int PAID = 1;
public static final int SHIPPED = 2;
public static final int DONE = 3;
private int status = UNPAID;
public void process() {
if (status == UNPAID) {
System.out.println("当前订单未支付,执行支付逻辑...");
status = PAID;
} else if (status == PAID) {
System.out.println("订单已支付,执行发货逻辑...");
status = SHIPPED;
} else if (status == SHIPPED) {
System.out.println("订单已发货,执行收货逻辑...");
status = DONE;
} else if (status == DONE) {
System.out.println("订单已完成");
} else {
System.out.println("未知订单状态");
}
}
}
测试:
java
public class Test {
public static void main(String[] args) {
Order order = new Order();
order.process(); // 支付
order.process(); // 发货
order.process(); // 收货
order.process(); // 已完成
}
}
这种方式短期内可用,但问题比较明显:
1、集中式 if-else:
所有状态逻辑都在一个方法里面,方法不断膨胀,维护困难。
2、违反开闭原则:
新增状态时必须修改这个方法的代码,容易引入 bug。
3、状态切换逻辑分散:
可能在多个方法都有类似的 if-else,改动的时候要到处找。
4、可读性差:
状态和行为耦合得很紧,不直观。
2.2、状态模式实现
订单状态流转
1、定义状态接口
java
public interface OrderState {
void handle(OrderContext context);
}
2、具体状态类
java
public class UnpaidState implements OrderState {
public void handle(OrderContext context) {
System.out.println("当前订单未支付,执行支付逻辑...");
context.setState(new PaidState()); // 切换状态
}
}
public class PaidState implements OrderState {
public void handle(OrderContext context) {
System.out.println("订单已支付,执行发货逻辑...");
context.setState(new ShippedState());
}
}
public class ShippedState implements OrderState {
public void handle(OrderContext context) {
System.out.println("订单已发货,执行收货逻辑...");
context.setState(new DoneState());
}
}
public class DoneState implements OrderState {
public void handle(OrderContext context) {
System.out.println("订单已完成");
}
}
3、环境类
java
public class OrderContext {
private OrderState state;
public OrderContext(OrderState state) { this.state = state; }
public void setState(OrderState state) { this.state = state; }
public void request() { state.handle(this); }
}
测试
java
public class Test {
public static void main(String[] args) {
OrderContext order = new OrderContext(new UnpaidState());
order.request(); // 支付
order.request(); // 发货
order.request(); // 收货
order.request(); // 已完成
}
}
输出:
当前订单未支付,执行支付逻辑...
订单已支付,执行发货逻辑...
订单已发货,执行收货逻辑...
订单已完成
基于前面的if-else和状态模式都需要多次去调用方法,因此可以对调用次数进行优化。
2.3、最终版
1、关于if-else的优化
java
public class Order {
private int status = 0;
private static final List<Integer> PROCESS_LIST = List.of(
0, // UNPAID
1, // PAID
2, // SHIPPED
3 // DONE
);
public void process() {
if (status == 0) {
System.out.println("未支付 -> 支付");
status = 1;
} else if (status == 1) {
System.out.println("已支付 -> 发货");
status = 2;
} else if (status == 2) {
System.out.println("已发货 -> 收货");
status = 3;
} else {
System.out.println("订单完成");
}
}
public static void main(String[] args) {
Order order = new Order();
PROCESS_LIST.forEach(s -> order.process());
}
}
这样避免了写 4 行 order.process(),但 逻辑依旧集中在一个方法里,只是调用更"批量"了。
2、状态模式下的优化
状态模式下,我们可以更灵活地用集合来管理状态流转过程,而且不用去写 if-else。
例子:
java
interface State {
void handle(OrderContext ctx);
}
class UnpaidState implements State {
public void handle(OrderContext ctx) {
System.out.println("当前订单未支付 -> 执行支付逻辑...");
ctx.setState(new PaidState());
}
}
class PaidState implements State {
public void handle(OrderContext ctx) {
System.out.println("订单已支付 -> 执行发货逻辑...");
ctx.setState(new ShippedState());
}
}
class ShippedState implements State {
public void handle(OrderContext ctx) {
System.out.println("订单已发货 -> 执行收货逻辑...");
ctx.setState(new DoneState());
}
}
class DoneState implements State {
public void handle(OrderContext ctx) {
System.out.println("订单已完成");
}
}
class OrderContext {
private State state;
public OrderContext(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void process() {
state.handle(this);
}
}
驱动代码:用集合 + 循环执行
java
public class TestOrder {
public static void main(String[] args) {
OrderContext order = new OrderContext(new UnpaidState());
// 一直循环直到状态是 DoneState
while (!(order.state instanceof DoneState)) {
order.process();
}
// 最后一遍处理完成状态
order.process();
}
}
特点
- 不用写多行 request(),直接用循环驱动
- 如果状态机变长/变短,不影响调用逻辑
- 也可以设计一个 List 状态链 提前加载好,遍历一次性跑完
3、ArrayList 配置"状态流"
状态模式也可以结合 状态数组:
java
List<State> flow = List.of(
new UnpaidState(),
new PaidState(),
new ShippedState(),
new DoneState()
);
OrderContext ctx = new OrderContext(flow.get(0));
for (State state : flow) {
ctx.setState(state);
ctx.process();
}
- 优势:业务状态流程可以从配置文件 甚至数据库加载,不用改代码
- 实现可拥抱灵活性,比如读取"审批流"、"工单流"这些可配置流程
3、总结
如下所示:

总结
状态模式是一种行为型设计模式,允许对象在内部状态改变时改变其行为。模式中包含上下文、抽象状态和具体状态角色。
优点包括解耦客户端和状态对象,可扩展性强,避免大量条件语句。缺点是可能增加系统类的数量和复杂性。适用场景如自动售货机的状态转换、线程状态管理等。
参考文章: