squirrel-foundation java狀態機

介紹

squirrel-foundation:輕量級java有限狀態機

狀態機的要素

狀態機可歸納爲4個要素,即現態、條件、動作、次態。“現態”和“條件”是因,“動作”和“次態”是果。

現態:是指當前所處的狀態。
條件:又稱爲事件。當一個條件被滿足,將會觸發一個動作,或者執行一次狀態的遷移。
動作:條件滿足後執行的動作。動作執行完畢後,可以遷移到新的狀態,也可以仍舊保持原狀態。動作不是必需的,當條件滿足後,也可以不執行任何動作,直接遷移到新狀態。
次態:條件滿足後要遷往的新狀態。“次態”是相對於“現態”而言的,“次態”一旦被激活,就轉變成新的“現態”了。

入門級Demo

導入依賴

<dependency>
    <groupId>org.squirrelframework</groupId>
    <artifactId>squirrel-foundation</artifactId>
    <version>0.3.8</version>
</dependency>

StateMachine接口需要以下4種泛型參數。
T代表實現的狀態機類型。
S代表實現的狀態類型。
E代表實現的事件類型。
C代表實現的外部上下文類型。

定義S:即狀態類型

public enum  MyState {
    A,
    B,
    C,
    D;
}

定義E:即事件類型

public enum  MyEvent {
    ToA,ToB,ToC,ToD;
}

定義C:即上下文類型,只有一個num字段

public class MyContext {

    public int num = 0;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

}

定義T:狀態機類型

/**
 * 定義我的狀態機:需繼承AbstractStateMachine
 */
public class MyStateMachine extends AbstractStateMachine<MyStateMachine, MyState, MyEvent, MyContext> {

    public void fun1(MyState from, MyState to, MyEvent event, MyContext context) {

        System.out.println("fun1() 方法執行了。。。。。。。。。。。。。 from:" + from + ", to:" + to +", event:" +event +", context:" + context.num );
    }

}

編寫main函數

 public static void main(String[] args) {
        StateMachineBuilder<MyStateMachine, MyState, MyEvent, MyContext> builder =
                StateMachineBuilderFactory.create(MyStateMachine.class, MyState.class, MyEvent.class, MyContext.class);

        /**
         * 條件爲:content.getNum 爲20的時候轉換,並執行fun1()方法
         */
        builder.externalTransition().from(MyState.A).to(MyState.B).on(MyEvent.ToB)
                .whenMvel("myCondition:::(context!=null && context.getNum() == 20)").callMethod("fun1");

        MyStateMachine machine = builder.newStateMachine(MyState.A);
        machine.start();
        System.out.println("currentState is " + machine.getCurrentState());
        MyContext context = new MyContext();
        context.setNum(20);
        machine.fire(MyEvent.ToB, context);
        System.out.println("currentState is " + machine.getCurrentState());
        
    }

結果打印

currentState is A
fun1() 方法執行了。。。。。。。。。。。。。 from:A, to:B, event:toB, context:20
currentState is B

添加監聽和註解開發

修改T,增加監聽

/**
 * 定義我的狀態機:需繼承AbstractStateMachine
 */
public class MyStateMachine extends AbstractStateMachine<MyStateMachine, MyState, MyEvent, MyContext> {

    public void fun1(MyState from, MyState to, MyEvent event, MyContext context) {
        System.out.println("fun1() 方法執行了。。。。。。。。。。。。。 from:" + from + ", to:" + to + ", event:" + event + ", context:" + context.num);
    }

     /**
     * 約定大於配置
     * like:
     * transitFrom[fromStateName]To[toStateName]On[eventName]When[conditionName]
     * transitFrom[fromStateName]To[toStateName]On[eventName]
     * transitFromAnyTo[toStateName]On[eventName]
     * transitFrom[fromStateName]ToAnyOn[eventName]
     * transitFrom[fromStateName]To[toStateName]
     * on[eventName]
     */
    protected void transitFromAToBOnToB(MyState from, MyState to, MyEvent event, MyContext context){
        System.out.println("從A--->B執行....約定大於配置");
    }

    /**
     * exitA執行
     */
    protected void exitA(MyState from, MyState to, MyEvent event, MyContext context){
        System.out.println("exitA()方法執行了。。。。。。。。");
    }




    public class DeclarativeListener {

        @OnTransitionBegin
        public void transitionBegin(MyEvent event) {
            // method annotated with TransitionBegin will be invoked when transition begin...
            System.out.println("轉換開始執行.." + event);
        }
        /**
         * 條件:context.num == 20 || event.name().equals("toC")
         */
        @OnTransitionBegin(when = "context.num == 20 || event.name().equals(\"toC\")")
        public void begins(MyState from, MyState to, MyEvent event, MyContext context) {
            System.out.println("begins 執行了, from:" + from + ", to:" + to + ", event:" + event + ", context:" + context.num);
        }

        @OnTransitionEnd
        @ListenerOrder(10) // Since 0.3.1 ListenerOrder can be used to insure listener invoked orderly
        public void transitionEnd() {
            // method annotated with TransitionEnd will be invoked when transition end...
            // the method must be public and return nothing
            System.out.println("轉換結束執行..");
        }

        @OnTransitionComplete
        public void transitionComplete(String from, String to, MyEvent event, Integer context) {
            // method annotated with TransitionComplete will be invoked when transition complete...
            System.out.println("轉換成功執行..");
        }

        @OnTransitionDecline
        public void transitionDeclined(String from, MyEvent event, Integer context) {
            // method annotated with TransitionDecline will be invoked when transition declined...
            System.out.println("轉換拒絕執行..");
        }

        @OnBeforeActionExecuted
        public void onBeforeActionExecuted(Object sourceState, Object targetState,
                                           Object event, Object context, int[] mOfN, Action<?, ?, ?,?> action) {
            // method annotated with OnAfterActionExecuted will be invoked before action invoked
            System.out.println("狀態機內方法動作執行之前...111111111111111111111111111111111");
        }

        @OnAfterActionExecuted
        public void onAfterActionExecuted(Object sourceState, Object targetState,
                                          Object event, Object context, int[] mOfN, Action<?, ?, ?,?> action) {
            // method annotated with OnAfterActionExecuted will be invoked after action invoked
            System.out.println("狀態機內方法動作執行之後...222222222222222222222222222222222");
        }

        @OnActionExecException
        public void onActionExecException(Action<?, ?, ?,?> action, TransitionException e) {
            // method annotated with OnActionExecException will be invoked when action thrown exception
            System.out.println("轉換異常執行。。");
        }

    }

}

再次編寫Main函數

public static void main(String[] args) {
        StateMachineBuilder<MyStateMachine, MyState, MyEvent, MyContext> builder =
                StateMachineBuilderFactory.create(MyStateMachine.class, MyState.class, MyEvent.class, MyContext.class);

        /**
         * 條件爲:content.getNum 爲20的時候轉換,並執行fun1()方法
         */
        builder.externalTransition().from(MyState.A).to(MyState.B).on(MyEvent.ToB)
                .whenMvel("myCondition:::(context!=null && context.getNum() == 20)").callMethod("fun1");
        builder.externalTransition().from(MyState.A).to(MyState.C).on(MyEvent.ToC);

        MyStateMachine machine = builder.newStateMachine(MyState.A);
        machine.addDeclarativeListener(machine.new DeclarativeListener());
        machine.start();
        System.out.println("currentState is " + machine.getCurrentState());
        MyContext context = new MyContext();
        context.setNum(20);
        machine.fire(MyEvent.ToB, context);
        System.out.println("currentState is " + machine.getCurrentState());

    }

結果打印

currentState is A
begins 執行了, from:A, to:null, event:ToB, context:20
轉換開始執行..ToB
狀態機內方法動作執行之前...111111111111111111111111111111111
exitA()方法執行了。。。。。。。。
狀態機內方法動作執行之後...222222222222222222222222222222222
狀態機內方法動作執行之前...111111111111111111111111111111111
fun1() 方法執行了。。。。。。。。。。。。。 from:A, to:B, event:ToB, context:20
狀態機內方法動作執行之後...222222222222222222222222222222222
狀態機內方法動作執行之前...111111111111111111111111111111111
從A--->B執行....約定大於配置
狀態機內方法動作執行之後...222222222222222222222222222222222
轉換成功執行..
轉換結束執行..
currentState is B
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章