一、状态变化
拿支付来说,正常流程如下
- 订单创建 ---> 订单确认
- 订单确认 ---> 已支付
- 已支付 ---> 交易成功
不合法的流程
- 订单创建 ---> 交易成功
而状态的变化,通常是靠事件来驱动的,因此我们可以设计一个状态机,存储哪些状态 + 什么样的事件 => 新的状态
代码实现时,我们 可以把 原状态+事件 作为key,新的状态作为 value
项目启动时,通过 静态代码块 初始化那些合法的状态变化到 hashmap 中,使用时,通过查询 map 是否存在这样的key所对应的 value,存在则表示允许状态转移,否则抛异常。
所谓的事件,通常都是一个枚举类,用来表示事件类型。
二、代码实现如下
定义一个接口
java
public interface StateMachine<STATE, EVENT> {
/**
* 状态机转移
*
* @param state
* @param event
* @return
*/
STATE transition(STATE state, EVENT event);
}
在定义一个基类,实现该接口
java
public class BaseStateMachine<STATE, EVENT> implements StateMachine<STATE, EVENT> {
private Map<String, STATE> stateTransitions = new HashMap<>();
protected void putTransition(STATE origin, EVENT event, STATE target) {
stateTransitions.put(Joiner.on("_").join(origin, event), target);
}
@Override
public STATE transition(STATE state, EVENT event) {
STATE target = stateTransitions.get(Joiner.on("_").join(state, event));
if (target == null) {
throw new BizException("state = " + state + " , event = " + event, STATE_MACHINE_TRANSITION_FAILED);
}
return target;
}
}
具体的业务需要时,继承该类,往map添加具体的状态即可 例如:支付的如下
java
public class OrderStateMachine extends BaseStateMachine<TradeOrderState, TradeOrderEvent> {
public static final OrderStateMachine INSTANCE = new OrderStateMachine();
{
putTransition(TradeOrderState.CREATE, TradeOrderEvent.CONFIRM, TradeOrderState.CONFIRM);
putTransition(TradeOrderState.CONFIRM, TradeOrderEvent.PAY, TradeOrderState.PAID);
putTransition(TradeOrderState.PAID, TradeOrderEvent.FINISH, TradeOrderState.FINISH);
}
}