ToB企服应用市场:ToB评测及商务社交产业平台

标题: Squirrel状态机-从原理探究到最佳实践 [打印本页]

作者: 笑看天下无敌手    时间: 2023-2-3 08:39
标题: Squirrel状态机-从原理探究到最佳实践
作者:京东物流 郑朋辉

1 简介

Squirrel状态机是一种用来进行对象行为建模的工具,主要描述对象在它的生命周期内所经历的状态,以及如何响应来自外界的各种事件。比如订单的创建、已支付、发货、收获、取消等等状态、状态之间的控制、触发事件的监听,可以用该框架进行清晰的管理实现。使用状态机来管理对象生命流的好处更多体现在代码的可维护性、可测试性上,明确的状态条件、原子的响应动作、事件驱动迁移目标状态,对于流程复杂易变的业务场景能大大减轻维护和测试的难度。
2 基本概念

2.1 Squirrel状态机定义

Squirrel状态机是一种有限状态机,有限状态机是指对象有一个明确并且复杂的生命流(一般而言三个以上状态),并且在状态变迁存在不同的触发条件以及处理行为。
2.2 Squirrel状态机要素

Squirrel状态机可归纳为4个要素,即现态、条件、动作、次态。“现态”和“条件”是因,“动作”和“次态”是果。
3 实现原理

3.1 店铺审核CASE

举例,京东线上开店需要经过审核才能正式上线,店铺状态有待审核、已驳回、已审核,对应操作有提交审核,审核通过,审核驳回动作。现在需要实现一个店铺审核流程的需求。
3.2 方案对比

3.2.1 常用if-else或switch-case实现(分支模式)


图1.if-else/switch-case模式实现流程图
3.2.2 状态机实现


图2.状态机模式实现流程图
3.2.3 对比

通过引入状态机,可以去除大量if-else if-else或者switch-case分支结构,直接通过当前状态和状态驱动表查询行为驱动表,找到具体行为执行操作,有利于代码的维护和扩展。
3.3 实现原理


图3.状态机创建流程图
4 实践分享

4.1 环境依赖
  1. <dependency>
  2. <groupId>org.squirrelframework</groupId>
  3. <artifactId>squirrel-foundation</artifactId>
  4. <version>0.3.9</version>
  5. </dependency>
复制代码
4.2 状态机元素定义:状态、事件
  1. // 店铺审核状态
  2. public Enum ShopInfoAuditStatusEnum{
  3. audit(0,"待审核"),
  4. agree(1,"审核通过"),
  5. reject(2,"审核驳回");
  6. }
  7. // 店铺审核事件
  8. public Enum ShopInfoAuditEvent{
  9. SUBMIT, // 提交
  10. AGREE, // 同意
  11. REJECT; // 驳回
  12. }
复制代码
4.3 构建StateMachineBuilder实例
  1. /**
  2. * StateMachineBuilder实例
  3. */
  4. public class StateMachineEngine <T extends UntypedStateMachine, S, E, C> implements ApplicationContextAware{
  5. private ApplicationContext applicationContext;
  6. private static Map<String,UntypedStateMachineBuilder> builderMap = new HashMap<String,UntypedStateMachineBuilder>();
  7. @Override
  8. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  9. this.applicationContext = applicationContext;
  10. }
  11. @Transactional
  12. public void fire(Class<T> machine, S state, E event, C context) {
  13. StateMachineBuilder stateMachineBuilder = this.getStateMachineBuilder(machine);
  14. StateMachine stateMachine = stateMachineBuilder.newStateMachine(state,applicationContext);
  15. stateMachine.fire(event, context);
  16. }
  17. private StateMachineBuilder getStateMachineBuilder(Class<T> stateMachine){
  18. UntypedStateMachineBuilder stateMachineBuilder = builderMap.get(stateMachine.getName());
  19. if(stateMachineBuilder == null){
  20. stateMachineBuilder = StateMachineBuilderFactory.create(stateMachine,ApplicationContext.class);
  21. builderMap.put(stateMachine.getName(),stateMachineBuilder);
  22. }
  23. return stateMachineBuilder;
复制代码
4.4 创建具体店铺状态审核状态机
  1. /**
  2. * 店铺审核状态机
  3. */
  4. @States({
  5. @State(name = "audit"),
  6. @State(name = "agree"),
  7. @State(name = "reject")
  8. })
  9. @Transitions({
  10. @Transit(from = "audit", to = "agree", on = "AGREE", callMethod = "agree"),
  11. @Transit(from = "audit", to = "reject", on = "REJECT", callMethod = "reject"),
  12. @Transit(from = "reject", to = "audit", on = "SUBMIT", callMethod = "submit"),
  13. @Transit(from = "agree", to = "audit", on = "SUBMIT", callMethod = "submit"),
  14. @Transit(from = "audit", to = "audit", on = "SUBMIT", callMethod = "submit"),
  15. })
  16. @StateMachineParameters(stateType=ShopInfoAuditStatusEnum.class, eventType=ShopInfoAuditEvent.class, contextType=ShopInfoAuditStatusUpdateParam.class)
  17. public class ShopInfoAuditStateMachine extends AbstractUntypedStateMachine {
  18. private ApplicationContext applicationContext;
  19. public ShopInfoAuditStateMachine(){}
  20. public ShopInfoAuditStateMachine(ApplicationContext applicationContext) {
  21. this.applicationContext = applicationContext;
  22. }
  23. // 审核通过业务逻辑
  24. public void agree(ShopInfoAuditStatusEnum fromState, ShopInfoAuditStatusEnum toState, ShopInfoAuditEvent event, ShopInfoAuditStatusUpdateParam param) {
  25. this.agree(fromState,toState,event,param);
  26. }
  27. // 审核驳回业务逻辑
  28. public void reject(ShopInfoAuditStatusEnum fromState, ShopInfoAuditStatusEnum toState, ShopInfoAuditEvent event, ShopInfoAuditStatusUpdateParam param) {
  29. this.reject(fromState,toState,event,param);
  30. }
  31. // 提交业务逻辑
  32. public void submit(ShopInfoAuditStatusEnum fromState, ShopInfoAuditStatusEnum toState, ShopInfoAuditEvent event, ShopInfoAuditStatusUpdateParam param) {
  33. this.submit(fromState,toState,event,param);
  34. }
复制代码
4.5 客户端调用
  1. // 调用端
  2. main{
  3. StateMachineEngine stateMachineEngine = applicationContext.getBean(StateMachineEngine.class);
  4. // 审核通过调case
  5. stateMachineEngine.fire(ShopInfoAuditStateMachine.class,ShopInfoAuditStatusEnum.audit,ShopInfoAuditEvent.AGREE,param);
  6. // 审核驳回case
  7. stateMachineEngine.fire(ShopInfoAuditStateMachine.class,ShopInfoAuditStatusEnum.audit,ShopInfoAuditEvent.REJECT,param);
  8. }
复制代码
5 总结

状态机很好的帮我们处理了对象状态的流转、事件的监听以及外界的各种事件的响应。从代码设计角度减少了大量if-else/switch-case逻辑判断,提高了代码的可维护性、扩展性,方便管理和测试。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4