介紹
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