什么是状态机
状态机就是状态模式的一种实现,状态模式
(State Pattern)是一种行为设计模式,让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。
状态机的全称是有限状态自动机(FSM,有限状态机wiki),有多种类型的动作:
- 进入动作(entry action):在进入状态时进行
- 退出动作(exit action):在退出状态时进行
- 输入动作:依赖于当前状态和输入条件进行
- 转移动作:在进行特定转移时进行
它可以使用如下图的状态转移图来表示,也可以用状态转移表来表示
在状态机中有四个主要概念:
- state(状态): 一个状态机至少包含两个状态,如上图中的opened、closed两个状态
- event(事件): 就是触发状态变化的一个扳机,所以有些地方也叫trigger
- action(动作): 事件发生后需要执行的动态
- transition(转换过程): 从一个状态转化到另一个状态的全部过程
状态机选型
- stateless4j(github地址):stateless(c#)的Java版本
- 优点: 轻量、简单易用、性能良好
- 缺点: 功能有限,无法满足复杂场景(如不支持state持久化、缺少扩展点等)
- Squirrel(github地址):
- 优点: 功能丰富,易于扩展
- 缺点: 有一定学习成本
- Spring Statemachine(github地址):
- 优点: Spring生态,功能丰富,有丰富的扩展点
- 缺点: StateMachine实例创建比较重
Spring状态机Quick Start
github demo地址: https://github.com/RussXia/spring-state-machine-sample
订单状态:
public enum OrderStatusEnum {
UNPAID(1, "待支付"),
WAITING_DELIVERY(2, "待发货"),
WAITING_FOR_RECEIVE(3, "待收货"),
RECEIVED(4, "已签收"),
REJECTED(5, "已拒收"),
}
订单事件
public enum OrderEventEnum {
PAY(1, "支付"),
DELIVERY(2, "发货"),
RECEIVE(3, "收货"),
REJECT(4, "拒收"),
}
状态机配置:
@Override
public void configure(StateMachineTransitionConfigurer<OrderStatusEnum, OrderEventEnum> transitions)
throws Exception {
transitions
.withExternal()
.source(OrderStatusEnum.UNPAID).target(OrderStatusEnum.WAITING_DELIVERY)
.event(OrderEventEnum.PAY).action(simpleAction, errorAction)
.and()
.withExternal()
.source(OrderStatusEnum.WAITING_DELIVERY).target(OrderStatusEnum.WAITING_FOR_RECEIVE)
.event(OrderEventEnum.DELIVERY).action(simpleAction, errorAction)
.and()
.withExternal()
.source(OrderStatusEnum.WAITING_FOR_RECEIVE).target(OrderStatusEnum.RECEIVED)
.event(OrderEventEnum.RECEIVE).action(simpleAction, errorAction)
.and()
.withExternal()
.source(OrderStatusEnum.WAITING_FOR_RECEIVE).target(OrderStatusEnum.REJECTED)
.event(OrderEventEnum.REJECT).action(rejectGoodsAction, errorAction);
}