squirrel-foundation java狀態(tài)機(jī)

參考鏈接:http://hekailiang.github.io/squirrel/
Squirrel使用 | 城的燈

介紹

squirrel-foundation:輕量級(jí)java有限狀態(tài)機(jī)

狀態(tài)機(jī)的要素

狀態(tài)機(jī)可歸納為4個(gè)要素,即現(xiàn)態(tài)、條件、動(dòng)作、次態(tài)?!艾F(xiàn)態(tài)”和“條件”是因,“動(dòng)作”和“次態(tài)”是果。

現(xiàn)態(tài):是指當(dāng)前所處的狀態(tài)。
條件:又稱為事件。當(dāng)一個(gè)條件被滿足,將會(huì)觸發(fā)一個(gè)動(dòng)作,或者執(zhí)行一次狀態(tài)的遷移。
動(dòng)作:條件滿足后執(zhí)行的動(dòng)作。動(dòng)作執(zhí)行完畢后,可以遷移到新的狀態(tài),也可以仍舊保持原狀態(tài)。動(dòng)作不是必需的,當(dāng)條件滿足后,也可以不執(zhí)行任何動(dòng)作,直接遷移到新狀態(tài)。
次態(tài):條件滿足后要遷往的新狀態(tài)?!按螒B(tài)”是相對(duì)于“現(xiàn)態(tài)”而言的,“次態(tài)”一旦被激活,就轉(zhuǎn)變成新的“現(xiàn)態(tài)”了。

入門級(jí)Demo

導(dǎo)入依賴
<dependency>
    <groupId>org.squirrelframework</groupId>
    <artifactId>squirrel-foundation</artifactId>
    <version>0.3.8</version>
</dependency>

StateMachine接口需要以下4種泛型參數(shù)。
T代表實(shí)現(xiàn)的狀態(tài)機(jī)類型。
S代表實(shí)現(xiàn)的狀態(tài)類型。
E代表實(shí)現(xiàn)的事件類型。
C代表實(shí)現(xiàn)的外部上下文類型。

定義S:即狀態(tài)類型
public enum  MyState {
    A,
    B,
    C,
    D;
}
定義E:即事件類型
public enum  MyEvent {
    ToA,ToB,ToC,ToD;
}
定義C:即上下文類型,只有一個(gè)num字段
public class MyContext {

    public int num = 0;

    public int getNum() {
        return num;
    }

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

}
定義T:狀態(tài)機(jī)類型
/**
 * 定義我的狀態(tài)機(jī):需繼承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() 方法執(zhí)行了。。。。。。。。。。。。。 from:" + from + ", to:" + to +", event:" +event +", context:" + context.num );
    }

}
編寫main函數(shù)
 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的時(shí)候轉(zhuǎn)換,并執(zhí)行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());
        
    }
結(jié)果打印
currentState is A
fun1() 方法執(zhí)行了。。。。。。。。。。。。。 from:A, to:B, event:toB, context:20
currentState is B

添加監(jiān)聽和注解開發(fā)

修改T,增加監(jiān)聽
/**
 * 定義我的狀態(tài)機(jī):需繼承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() 方法執(zhí)行了。。。。。。。。。。。。。 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執(zhí)行....約定大于配置");
    }

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




    public class DeclarativeListener {

        @OnTransitionBegin
        public void transitionBegin(MyEvent event) {
            // method annotated with TransitionBegin will be invoked when transition begin...
            System.out.println("轉(zhuǎn)換開始執(zhí)行.." + 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 執(zhí)行了, 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("轉(zhuǎn)換結(jié)束執(zhí)行..");
        }

        @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("轉(zhuǎn)換成功執(zhí)行..");
        }

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

        @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("狀態(tài)機(jī)內(nèi)方法動(dòng)作執(zhí)行之前...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("狀態(tài)機(jī)內(nèi)方法動(dòng)作執(zhí)行之后...222222222222222222222222222222222");
        }

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

    }

}
再次編寫Main函數(shù)
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的時(shí)候轉(zhuǎn)換,并執(zhí)行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());

    }
結(jié)果打印
currentState is A
begins 執(zhí)行了, from:A, to:null, event:ToB, context:20
轉(zhuǎn)換開始執(zhí)行..ToB
狀態(tài)機(jī)內(nèi)方法動(dòng)作執(zhí)行之前...111111111111111111111111111111111
exitA()方法執(zhí)行了。。。。。。。。
狀態(tài)機(jī)內(nèi)方法動(dòng)作執(zhí)行之后...222222222222222222222222222222222
狀態(tài)機(jī)內(nèi)方法動(dòng)作執(zhí)行之前...111111111111111111111111111111111
fun1() 方法執(zhí)行了。。。。。。。。。。。。。 from:A, to:B, event:ToB, context:20
狀態(tài)機(jī)內(nèi)方法動(dòng)作執(zhí)行之后...222222222222222222222222222222222
狀態(tài)機(jī)內(nèi)方法動(dòng)作執(zhí)行之前...111111111111111111111111111111111
從A--->B執(zhí)行....約定大于配置
狀態(tài)機(jī)內(nèi)方法動(dòng)作執(zhí)行之后...222222222222222222222222222222222
轉(zhuǎn)換成功執(zhí)行..
轉(zhuǎn)換結(jié)束執(zhí)行..
currentState is B

不足之處,歡迎指正!謝謝!?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者。

友情鏈接更多精彩內(nèi)容