zoukankan      html  css  js  c++  java
  • 无状态状态机--cola stateMachine

    1.介绍

      cola stateMachine 是阿里大神开发的状态,可能是闲暇时开发一个简单工具。这个状态和spring stateMachine 有很大的区别。它有一个非常优秀的特性: 无状态

      可能理解起来有点矛盾,状态机是无状态的,那为什么叫做状态机。其实,状态机本身是可以无状态,它只是管理状态的一个工具。或者称它为 DSL 语法的一种实现体。它能够帮助我们更好对单据状态的扭转表达。如同XML那每个配置都是要符合要求一定结构才行,只有配置正确了,它的属性值才会生效。 所以不必要从字面去理解状态机有无状态。

       在上篇博客中可以得出spring stateMachine 有很多弊端,其中最大的弊端就是来源它本身是有状态的,导致了我们需要新增很多手段才能使其对内存消耗降低(自定义状态机线程池,是状态机可以重复利用,不是每次都是new一个对象)。这时候体现出了无状态的状态机好处了。无状态的状态机,表现了它可以被 单例化 ,表明了状态机是可以重复利用的,先天解决了有状态带来的不必要的内存消耗。

      这不是说spring stateMachine 不好,反而是它太好了。好的有点过分,spring stateMachine 它中很多优秀的功能,然而这些功能在我们日常开发中,是根本用不到的。导致了spring stateMachine为了实现 ppt 上功能,新增很多不必要的东西,导致spring stateMachine 显得太过笨重。这样就表现的 cola stateMachine 优势更加明显,如果你对状态不是很了解的话,你可以看一下这篇文章(https://blog.csdn.net/significantfrank/article/details/104996419),就会觉得状态其实根本不难,而且不需要做成spring stateMachine那般笨重。

      阿里出品必属精品(不是狗吹阿里),但是阿里出品通常都会无极而终(毕竟别人不是专门做开源工具的,时间精力有限)。为什么说阿里大神开发的cola stateMachine 说他是闲暇的时间开发,是因为他还有很多场景是无法实现的。需要我们自己结合我们的业务线基础上做二次开发。其次全文看下来主要是在将cola架构,所以我才有这样的怀疑。

    2.优势

      1.代码简单,易于学习,便于根据我们的业务线基础上做二次开发。

          2.无状态,减少内存消耗,线程先天安全。

      3.先天支持事务

      4.先天会自己抛出异常,不会像spring stateMachine出现将异常吃掉情况(当然通过反射确实可以将异常抛出)。

      5.包小,摒弃了spring stateMachine中没有必要的功能,功能相对单一,包自然就小了。同时减少了资源的浪费。

    3.状态机基础模型

      1.State:状态
      2.Event:事件,状态由事件触发,引起变化
      3.Transition:流转,表示从一个状态到另一个状态
      4.External Transition:外部流转,两个不同状态之间的流转
      5.Internal Transition:内部流转,同一个状态之间的流转
      6.Condition:条件,表示是否允许到达某个状态
      7.Action:动作,到达某个状态之后,可以做什么
      8.StateMachine:状态机

    4.基本使用

      

    
    

    tateMachineBuilder<States, Events, Context> builder = StateMachineBuilderFactory.create();
    //external transition
    builder.externalTransition()
      .from(States.STATE1)
      .to(States.STATE2)
      .on(Events.EVENT1)
      .when(checkCondition())
      .perform(doAction());

    
    

    //internal transition
    builder.internalTransition()
      .within(States.STATE2)
      .on(Events.INTERNAL_EVENT)
      .when(checkCondition())
      .perform(doAction());

    
    

    //external transitions
    builder.externalTransitions()
      .fromAmong(States.STATE1, States.STATE2, States.STATE3)
      .to(States.STATE4)
      .on(Events.EVENT4)
      .when(checkCondition())
      .perform(doAction());

    builder.build(machineId);

    
    

    StateMachine<States, Events, Context> stateMachine = StateMachineFactory.get(machineId);
    stateMachine.showStateMachine();

    5.自定义开发

      在使用cola stateMachine的时候,有一种业务场景是当前状态机无法实现的,就是当 当前状态和事件是同一个,但是目标状态不一样的时候,这个时候cola是无法实现。比如:退货出库,销售出库创建出库单的时候,他们的事件都是 createBill ,但是目标状态由于业务上不同,导致了目标状态是 待出库 和 待拣货下架。当然你可以通过不同事件来处理这个场景,比如定义:退货出库操作,销售出库操作,不在使用相同的事件。或者在业务代码上处理,但是个人认为这是一种这种折中方案。我认为将checkCondition 方法功能相对弱化了。checkCondition的判断在cola stateMachine中只是做了if 的判断。 现实场景中有很多 if/else if/else判断。在自定义开发中,我就加强了这个。为了达到这种判断,我新增一种类型 CHOOSE类型,这种类型是外部状态扭转的一种实现,本人比较懒为了不改大神的代码基础上做了,简单的新增类型。不然要将大神的代码进行 大改。

    由于大神的源码比较简单,只关公面前耍大刀展示部分代码实现:

    public class ChooseTransitionBuilderImpl<S, E, C> implements ChooseExternalTransitionBuilder<S, E, C>, ChooseFrom<S, E, C>, ChooseOn<S, E, C> {
        /**
         * 状态机集合
         */
        final Map<S, State<S, E, C>> stateMap;
        /**
         * 源状态
         */
        private State<S, E, C> source;
        /**
         * 目标状态
         */
        protected State<S, E, C> target;
        /**
         * 状态扭转实体
         */
        private Transition<S, E, C> transition;
        /**
         * 状态扭转类型
         */
        final TransitionType transitionType;
    
        private E event;
    
        public ChooseTransitionBuilderImpl(Map<S, State<S, E, C>> stateMap, TransitionType transitionType) {
            this.stateMap = stateMap;
            this.transitionType = transitionType;
        }
    
    
        @Override
        public ChooseFrom<S, E, C> from(S stateId) {
            this.source = StateHelper.getState(stateMap, stateId);
            return this;
        }
    
        @Override
        public ChooseOn<S, E, C> on(E event) {
            this.event = event;
            return this;
        }
    
        @Override
        public ChooseOn<S, E, C> caseThen(Condition<C> condition, S stateId, Action<S, E, C> action) {
            target = StateHelper.getState(stateMap, stateId);
            transition = source.addTransitionByChoose(event, target, TransitionType.CHOOSE);
            transition.setAction(action);
            transition.setCondition(condition);
            return this;
        }
    
        @Override
        public void end(S stateId, Action<S, E, C> action) {
            target = StateHelper.getState(stateMap, stateId);
            transition = source.addTransitionByChoose(event, target, TransitionType.CHOOSE);
            transition.setAction(action);
            transition.setCondition(context -> true);
        }
    }
      @Override
        public Transition<S, E, C> addTransitionByChoose(E event, State<S, E, C> target, TransitionType transitionType) {
            verifyChoose(event);
            Transition<S, E, C> newTransition = new TransitionImpl<>();
            newTransition.setSource(this);
            newTransition.setTarget(target);
            newTransition.setEvent(event);
            newTransition.setType(transitionType);
            Debugger.debug("Begin to add Choose Transition: " + newTransition);
            List<Transition<S, E, C>> transitions;
            if (chooseTransitions.containsKey(event)) {
                transitions = chooseTransitions.get(event);
            } else {
                transitions = new ArrayList<>();
            }
            transitions.add(newTransition);
            eventHashMap.put(event,transitionType);
            chooseTransitions.put(event, transitions);
            return newTransition;
        }

    具体实现,会在我的gitee上有相关实现

    使用

        StateMachineBuilder<States, Events, Context> builder = StateMachineBuilderFactory.create();
            builder.chooseExternalTransitions()
                    .from(States.STATE1)
                    .on(Events.EVENT1)
                    .caseThen(checkCondition(false), States.STATE1, doAction())
                    .caseThen(checkCondition(true), States.STATE3, doAction())
                    .end(States.STATE4, doAction());

    大神的代码简单,容易读懂,所以非常适合二次开发,可以按照根据公司业务场景做二次开发。

    6.具体实现

    gitee仓库地址

    https://gitee.com/cola-demo-wx/wx-cola-demo

    参考链接

    https://blog.csdn.net/significantfrank/article/details/104996419

      

  • 相关阅读:
    JavaScript-Runoob-JS 参考手册 :JavaScript 对象
    JavaScript-Runoob-JS 实例 :JavaScript 总结
    JavaScript-Runoob-JS 实例 :JavaScript HTML DOM 实例
    JavaScript-Runoob-JS 实例 :JavaScript Browser 对象实例
    JavaScript-Runoob-JS 实例 :JavaScript 对象实例
    linux 下 php 安装 libevent
    linux 下 php 安装 event
    mybatis实战教程(mybatis in action),mybatis入门到精通
    将MapReduce的结果输出至Mysql数据库
    spring路径通配符
  • 原文地址:https://www.cnblogs.com/Zero-Jo/p/14622937.html
Copyright © 2011-2022 走看看