理解名词
先来理解状态机。
有限状态机(Finite State Machine),缩写为 FSM,简称为状态机。状态机有 3 个组成部分:状态(State)、事件(Event)、动作(Action)。其中,事件也称为转移条件(Transition Condition)。事件触发状态的转移及动作的执行。动作不是必须的,也可能只转移状态,不执行任何动作。
作用
状态模式一般用来实现状态机,将事件触发的状态转移和动作执行解耦,拆分到不同的状态类中。
适用场景
存在有限状态的系统,且状态不多,状态转移较简单,但事件触发执行的动作包含的业务逻辑较为复杂。例如:
- 工作流引擎
- 电商下单,外卖下单
不适用场景:
-
对于状态不多,状态转移简单,动作简单的状态机,使用分支逻辑法实现即可。
-
对于状态很多,状态转移比较复杂的状态机,应使用查表法实现。
代码示例
以外卖下单为例,存在的状态有已下单,配送中,配送完成,订单已超时,订单已取消。
首先,定义状态类接口
public interface IOrderState {
// 响应订单开始配送事件,默认实现为不支持,子类支持该事件时需要重写该方法
default void onDeliver(OrderStateMachine machine) {
throw new UnsupportedEventException();
}
// 响应订单开始配送完成事件,默认实现为不支持,子类支持该事件时需要重写该方法
default void onDeliverCompleted(OrderStateMachine machine) {
throw new UnsupportedEventException();
}
// 响应订单超时事件,默认实现为不支持,子类支持该事件时需要重写该方法
default void onOrderTimeout(OrderStateMachine machine) {
throw new UnsupportedEventException();
}
// 响应订单被取消事件,默认实现为不支持,子类支持该事件时需要重写该方法
default void onOrderCancel(OrderStateMachine machine) {
throw new UnsupportedEventException();
}
}
状态机类实现
public class OrderStateMachine {
private IOrderState currentState;
public OrderStateMachine() {
this.currentState = InitOrderState.getInstance();
}
public void onDeliver() {
this.currentState.onDeliver(this);
}
public void onDeliverCompleted() {
this.currentState.onDeliverCompleted(this);
}
public void onOrderTimeout() {
this.currentState.onOrderTimeout(this);
}
public void onOrderCancel() {
this.currentState.onOrderCancel(this);
}
初始订单状态类实现
public class InitOrderState implements IOrderState {
// 单例
private static final InitOrderState instance = new InitOrderState();
private InitOrderState() {}
public static InitOrderState getInstance() { return instance; }
@Override
public void onDeliver(OrderStateMachine machine) {
// 开始配送...执行一些动作,例如推送骑手信息到App,开始计时等操作
machine.setCurrentState(DeliverOrderState.getInstance());
}
@Override
public void onOrderCancel(OrderStateMachine machine) {
// 订单被取消...执行一些动作,例如退款
machine.setCurrentState(CancelOrderState.getInstance());
}
}
配送订单状态类实现
public class DeliverOrderState implements IOrderState {
// 单例
private static final DeliverOrderState instance = new DeliverOrderState();
private DeliverOrderState() {}
public static DeliverOrderState getInstance() { return instance; }
@Override
public void onDeliverCompleted(OrderStateMachine machine) {
// 配送已完成...执行一些动作,例如邀请评价,发放优惠券
machine.setCurrentState(CompleteOrderState.getInstance());
}
@Override
public void onOrderTimeout(OrderStateMachine machine) {
// 订单配送超时...执行一些动作,例如推送App告知超时,发放超时赔偿
machine.setCurrentState(TimeoutOrderState.getInstance());
}
}
业界经典实现
- Spring statemachine