参考链接:http://hekailiang.github.io/squirrel/
Squirrel使用 | 城的灯
介绍
squirrel-foundation:轻量级java有限状态机
状态机的要素
状态机可归纳为4个要素,即现态、条件、动作、次态。“现态”和“条件”是因,“动作”和“次态”是果。
现态:是指当前所处的状态。
条件:又称为事件。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。
入门级Demo
导入依赖
org.squirrelframework
squirrel-foundation
0.3.8
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 {
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 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 {
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 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
不足之处,欢迎指正!谢谢!☺