squirrel-foundation

  • Maven
  • 快速开始
  • 基础概念
  • 高级特性

Maven

当前最新发行版本

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

最新快照版本

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

快速开始

public class QuickStartSample {// 1. 定义状态机事件enum FSMEvent {ToA, ToB, ToC, ToD}// 2. 定义状态机类@StateMachineParameters(stateType=String.class, eventType=FSMEvent.class, contextType=Integer.class)static class StateMachineSample extends AbstractUntypedStateMachine {protected void fromAToB(String from, String to, FSMEvent event, Integer context) {System.out.println("Transition from '"+from+"' to '"+to+"' on event '"+event+"' with context '"+context+"'.");}protected void ontoB(String from, String to, FSMEvent event, Integer context) {System.out.println("Entry State \'"+to+"\'.");}}public static void main(String[] args) {// 3. 创建状态过渡流程UntypedStateMachineBuilder builder = StateMachineBuilderFactory.create(StateMachineSample.class);builder.externalTransition().from("A").to("B").on(FSMEvent.ToB).callMethod("fromAToB");builder.externalTransition().from("B").to("C").on(FSMEvent.ToC).callMethod("fromAToB");builder.onEntry("B").callMethod("ontoB");// 4. 使用状态机UntypedStateMachine fsm = builder.newStateMachine("A");fsm.fire(FSMEvent.ToB, 10);fsm.fire(FSMEvent.ToC);System.out.println("Current state is "+fsm.getCurrentState());}
}

控制台打印

Transition from 'A' to 'B' on event 'ToB' with context '10'.
Entry State 'B'.
Transition from 'B' to 'C' on event 'ToC' with context 'null'.
Current state is C

这样一个简单的demo就运行起来了。

基础概念

squirrel-foundation不仅支持fluent API和声明性方式来声明状态机,还能让用户能够以直接的方式定义操作方法。

  • StateMachine支持的四种参数类型

    • T:状态机
    • S:状态
    • E:事件
    • C:外部上下文
  • State Machine Builder
StateMachineBuilder<MyStateMachine, MyState, MyEvent, MyContext> builder =StateMachineBuilderFactory.create(MyStateMachine.class, MyState.class, MyEvent.class, MyContext.class);
  • Fluent API

State Machine Builder创建完成后,可以用Fluent API去定义状态/转换/动作

builder.externalTransition().from("A").to("B").on(FSMEvent.ToB).callMethod("fromAToB");

这段代码的含义是:从状态A通过ToB事件转变为状态B,同时触发fromAToB方法。

builder.internalTransition(TransitionPriority.HIGH).within(MyState.A).on(MyEvent.WithinA).perform(new MyAction());

internalTransition可以设置优先级,优先级用于在覆盖原始过渡,状态A在触发"WithinA"事件时调用"myAction",通过myAction实现一定的逻辑,使用internalTransition时在过渡完成后没有状态进入或退出

builder.externalTransition().from(MyState.C).to(MyState.D).on(MyEvent.CTOD).when(new Condition<MyContext>() {@Overridepublic boolean isSatisfied(MyContext context) {return context!=null && context.getValue()>80;}@Overridepublic String name() {return "MyCondition";}}).callMethod("myInternalTransitionCall");
builder.externalTransition().from(MyState.C).to(MyState.D).on(MyEvent.CTOD).whenMvel("MyCondition:::(context!=null && context.getValue()>80)").callMethod("myInternalTransitionCall");

当isSatisfied为true时触发状态变化。

默认方法调用,通过函数名即可确认调用函数。

 protected void transitFromAToBOnATOB(MyState from, MyState to, MyEvent event, MyContext context)
protected void transitFromAnyToBOnGoToB(MyState from, MyState to, MyEvent event, MyContext context)

其他的默认方法格式

 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]
  • 注解
    基于注解定义状态机
@States({@State(name = "A", entryCallMethod = "entryA", exitCallMethod = "exitA", initialState = true),@State(name = "B", entryCallMethod = "entryB", exitCallMethod = "exitB"),@State(name = "C", entryCallMethod = "entryC", exitCallMethod = "exitC"),@State(name = "D", entryCallMethod = "entryD", exitCallMethod = "exitD")
})
@Transitions({@Transit(from = "A", to = "B", on = "ATOB", callMethod = "toB"),@Transit(from = "B", to = "C", on = "BTOC", callMethod = "toC"),@Transit(from = "C", to = "D", on = "CTOD", callMethod = "toD")
})
@StateMachineParameters(stateType = MyState.class, eventType = MyEvent.class, contextType = MyContext.class)
public class DeclarativeMachine extends AbstractUntypedStateMachine {public void entryA(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---entryA");}public void exitA(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---exitA");}public void entryB(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---entryB");}public void exitB(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---exitB");}public void entryC(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---entryC");}public void exitC(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---exitC");}public void entryD(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---entryD");}public void exitD(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---exitD");}public void toB(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---toB");}public void toC(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---toC");}public void toD(MyState from, MyState to, MyEvent on, MyContext context){System.out.println("---toD");}}
 @Testpublic void testDeclarativeMachine(){UntypedStateMachineBuilder builder = StateMachineBuilderFactory.create(DeclarativeMachine.class);UntypedStateMachine fsm = builder.newAnyStateMachine(MyState.A);fsm.start();fsm.fire(MyEvent.ATOB);fsm.fire(MyEvent.BTOC);fsm.fire(MyEvent.CTOD);}

高级特性

  • 定义分层状态
    一个分层状态可能包含嵌套状态,一个子状态可能还有嵌套的子状态,嵌套可能会进行到任何深度。当分层状态处于活动状态时,有且只有一个子状态处于活跃状态。可以通过API和注解定义分层状态。

api

builder.defineSequentialStatesOn(MyState.A, MyState.XINA, MyState.YINA);

annotation

@States({@State(name="A", entryCallMethod="entryA", exitCallMethod="exitA"),@State(parent="A", name="XINA", entryCallMethod="entryXINA", exitCallMethod="exitXINA", initialState=true),@State(parent="A", name="YINA", entryCallMethod="entryYINA", exitCallMethod="exitYINA")
})
  • 定义并行状态
    并行状态封装了一组子状态,当父状态处于活跃时,子状态可以都处于活跃状态。

api

 builder.defineParallelStatesOn(MyState.Root, MyState.RegionState1, MyState.RegionState2);builder.defineSequentialStatesOn(MyState.RegionState1, MyState.State11, MyState.State12);
builder.externalTransition().from(MyState.State11).to(MyState.State12).on(MyEvent.Event1);builder.defineSequentialStatesOn(MyState.RegionState2, MyState.State21, MyState.State22);
builder.externalTransition().from(MyState.State21).to(MyState.State22).on(MyEvent.Event2);

annotation

@States({@State(name="Root", entryCallMethod="enterRoot", exitCallMethod="exitRoot", compositeType=StateCompositeType.PARALLEL),@State(parent="Root", name="RegionState1", entryCallMethod="enterRegionState1", exitCallMethod="exitRegionState1"),@State(parent="Root", name="RegionState2", entryCallMethod="enterRegionState2", exitCallMethod="exitRegionState2")
})
  • 定义上下文事件

针对不同用例定义了三种类型的上下文事件。
启动/终止事件:状态机启动/终止时,将使用声明为启动/终止事件的事件。因此,用户可以区分调用的动作触发器,例如,当状态机正在启动并进入其初始状态时,用户可以区分这些状态进入动作是由启动事件调用的。
完成事件:当所有并行状态都达到最终状态时,将自动触发完成事件。用户可以根据完成事件定义以下过渡。
api

builder.defineFinishEvent(HEvent.Start);
builder.defineTerminateEvent(HEvent.Terminate);
builder.defineStartEvent(HEvent.Finish);

annotation

@ContextEvent(terminateEvent = "RootToA")
public class ParallelStateMachine extends AbstractUntypedStateMachine {}
  • 使用历史记录保存和还原当前状态

  • 过渡类型
    过渡分为三种类型:

    • Internal Transition (内部过渡)
      不会引起状态的变换,即不会调用entry和exit方法。
    • Local Transition(本地过渡)
      不会退出当前状态,但子状态会重新进入
    • External Transition (外部过渡)
      退出当前状态

api

builder.externalTransition().from(MyState.A).to(MyState.B).on(MyEvent.A2B);
builder.internalTransition().within(MyState.A).on(MyEvent.innerA);
builder.localTransition().from(MyState.A).to(MyState.CinA).on(MyEvent.intoC)

annotation

@Transitions({@Transition(from="A", to="B", on="A2B"), @Transition(from="A", on="innerA", type=TransitionType.INTERNAL),@Transition(from="A", to="CinA", on="intoC", type=TransitionType.LOCAL),})
  • 多态事件调度
    状态机生命周期所触发的事件

|--StateMachineEvent                        /* 所有状态机的事件 */   |--StartEvent                          /* 当状态机启动时触发  */ |--TerminateEvent                      /* 当状态机终止时触发 */ |--TransitionEvent                      /* 过渡时触发的事件 */ |--TransitionBeginEvent              /* 过渡开始时触发 */ |--TransitionCompleteEvent            /* 过渡完成时触发  */ |--TransitionExceptionEvent          /* 抛出异常时触发  */ |--TransitionDeclinedEvent           /* 过渡拒绝时触发  */ |--TransitionEndEvent                /* 结束过渡时触发(无论何种情况结束)*/
  • 声明式事件监听器
    为了简化状态机的使用,Squirrel 基础提供了一种声明式方法,可通过以下注解添加事件监听器,例如
  static class ExternalModule {@OnTransitionEnd@ListenerOrder(10) // Since 0.3.1 ListenerOrder can be used to insure listener invoked orderlypublic void transitionEnd() {// method annotated with TransitionEnd will be invoked when transition end...// the method must be public and return nothing}@OnTransitionBeginpublic void transitionBegin(TestEvent event) {// method annotated with TransitionBegin will be invoked when transition begin...}// 'event'(E), 'from'(S), 'to'(S), 'context'(C) and 'stateMachine'(T)可以用于MVEL脚本    @OnTransitionBegin(when="event.name().equals(\"toB\")")public void transitionBeginConditional() {// method will be invoked when transition begin while transition caused by event "toB"}@OnTransitionCompletepublic void transitionComplete(String from, String to, TestEvent event, Integer context) {// method annotated with TransitionComplete will be invoked when transition complete...}@OnTransitionDeclinepublic void transitionDeclined(String from, TestEvent event, Integer context) {// method annotated with TransitionDecline will be invoked when transition declined...}@OnBeforeActionExecutedpublic void onBeforeActionExecuted(Object sourceState, Object targetState, Object event, Object context, int[] mOfN, Action<?, ?, ?,?> action) {// method annotated with OnAfterActionExecuted will be invoked before action invoked  }@OnAfterActionExecutedpublic void onAfterActionExecuted(Object sourceState, Object targetState, Object event, Object context, int[] mOfN, Action<?, ?, ?,?> action) {// method annotated with OnAfterActionExecuted will be invoked after action invoked  }@OnActionExecExceptionpublic void onActionExecException(Action<?, ?, ?,?> action, TransitionException e) {// method annotated with OnActionExecException will be invoked when action thrown exception  }}ExternalModule externalModule = new ExternalModule();fsm.addDeclarativeListener(externalModule);...fsm.removeDeclarativeListener(externalModule);
  • 过渡扩展方法
    每个过渡事件还对AbstractStateMachine类具有相应的扩展方法,该扩展方法允许在客户状态机实现类中进行扩展。
protected void afterTransitionCausedException(Exception e, S fromState, S toState, E event, C context) {}protected void beforeTransitionBegin(S fromState, E event, C context) {}protected void afterTransitionCompleted(S fromState, S toState, E event, C context) {}protected void afterTransitionEnd(S fromState, S toState, E event, C context) {}protected void afterTransitionDeclined(S fromState, E event, C context) {}protected void beforeActionInvoked(S fromState, S toState, E event, C context) {}
  • 加权操作
    用户可以定义操作权重以调整操作执行顺序。状态进入/退出和状态转换期间的动作根据其权重值以升序排列。
    默认的权重是0,以before开头的权重为100,以after开头的权重是-100,注解设置权重的方法是 方法名:权重当方法名:ignore时,不会调用该方法。
public class WeightedActionTest {@Transitions({@Transit(from="A", to="B", on="ToB", callMethod="fromAToB"),@Transit(from="A", to="C", on="ToC", callMethod="fromAToC"),@Transit(from="A", to="D", on="ToD")})@States({@State(name="D", entryCallMethod="entryD")})@StateMachineParameters(stateType=String.class, eventType=String.class, contextType=Void.class)@ContextInsensitivestatic class UntypedStateMachineBase extends AbstractUntypedStateMachine {protected StringBuilder logger = new StringBuilder();protected void fromAToB(String from, String to, String event) {logger.append("fromAToB");}protected void transitFromAToBOnToB(String from, String to, String event) {logger.append("transitFromAToBOnToB");}protected void fromAToC(String from, String to, String event) {logger.append("fromAToC");}protected void entryD(String from, String to, String event) {logger.append("entryD");}@Overrideprotected void beforeActionInvoked(Object fromState, Object toState, Object event, Object context) {addOptionalDot();}private void addOptionalDot() {if (logger.length() > 0) {logger.append('.');}}public String consumeLog() {final String result = logger.toString();logger = new StringBuilder();return result;}}@Transitions({@Transit(from="A", to="B", on="ToB", callMethod="beforeFromAToB"),@Transit(from="A", to="B", on="ToB", callMethod="afterFromAToB"),@Transit(from="A", to="C", on="ToC", callMethod="goAToC1:+150"),@Transit(from="A", to="C", on="ToC", callMethod="goAToC2:-150"),})@States({@State(name="D", entryCallMethod="beforeEntryD"),@State(name="D", entryCallMethod="goEntryD:-150"),})static class UntypedStateMachineExt extends UntypedStateMachineBase {protected void beforeFromAToB(String from, String to, String event) {logger.append("beforeFromAToB");}protected void afterFromAToB(String from, String to, String event) {logger.append("afterFromAToB");}protected void goAToC1(String from, String to, String event) {logger.append("goAToC1");}protected void goAToC2(String from, String to, String event) {logger.append("goAToC2");}protected void beforeEntryD(String from, String to, String event) {logger.append("beforeEntryD");}protected void goEntryD(String from, String to, String event) {for(int i=0; i<10000; ++i) {RandomStringUtils.randomAlphabetic(10);}logger.append("goEntryD");}}@States({@State(name="D", entryCallMethod="entryD:+200") // override extension method weight})static class UntypedStateMachineExt2 extends UntypedStateMachineExt {}private UntypedStateMachineExt fsm;private StateMachineLogger logger;@Afterpublic void teardown() {if(fsm.getStatus()!=StateMachineStatus.TERMINATED)fsm.terminate(null);}@Beforepublic void setup() {UntypedStateMachineBuilder builder = StateMachineBuilderFactory.create(UntypedStateMachineExt.class);fsm = builder.newUntypedStateMachine("A", StateMachineConfiguration.create().enableDebugMode(true),new Object[0]);}/*** 测试 before:100 注解  默认方法  after:-100优先级*/@Testpublic void testBeforeExtension() {fsm.fire("ToB");assertThat(fsm.consumeLog(), is(equalTo("beforeFromAToB.fromAToB.transitFromAToBOnToB.afterFromAToB")));}/*** 测试设置优先级的调用顺序*/@Testpublic void testWeightTransitionAction() {fsm.fire("ToC");assertThat(fsm.consumeLog(), is(equalTo("goAToC1.fromAToC.goAToC2")));}/*** */@Testpublic void testWeightStateAction() {fsm.fire("ToD");assertThat(fsm.consumeLog(), is(equalTo("beforeEntryD.entryD.goEntryD")));}/*** 测试重写优先级的调用顺序*/@Testpublic void testOverrideWeight() {UntypedStateMachineBuilder builder = StateMachineBuilderFactory.create(UntypedStateMachineExt2.class);fsm = builder.newUntypedStateMachine("A");logger = new StateMachineLogger(fsm);logger.startLogging();fsm.fire("ToD");assertThat(fsm.consumeLog(), is(equalTo("entryD.beforeEntryD.goEntryD")));}/*** 测试ignore来忽略调用方法*/@Testpublic void testIgnoreWeight() {UntypedStateMachineBuilder builder = StateMachineBuilderFactory.create(UntypedStateMachineExt2.class);builder.onEntry("D").callMethod("entryD:ignore"); fsm = builder.newUntypedStateMachine("A");logger = new StateMachineLogger(fsm);logger.startLogging();fsm.fire("ToD");assertThat(fsm.consumeLog(), is(equalTo("beforeEntryD.goEntryD")));}
}
  • PostProcessor
    用户可以为特定类型的状态机注册后处理器,以便在实例化状态机后添加后处理逻辑,例如
// 1 User defined a state machine interfaceinterface MyStateMachine extends StateMachine<MyStateMachine, MyState, MyEvent, MyContext> {. . .}// 2 Both MyStateMachineImpl and MyStateMachineImplEx are implemented MyStateMachineclass MyStateMachineImpl implements MyStateMachine {. . . }class MyStateMachineImplEx implements MyStateMachine {. . .}// 3 User define a state machine post processorMyStateMachinePostProcessor implements SquirrelPostProcessor<MyStateMachine> {void postProcess(MyStateMachine component) {. . . }}  // 4 User register state machine post processSquirrelPostProcessorProvider.getInstance().register(MyStateMachine.class, MyStateMachinePostProcessor.class);
  • 状态机导出
    SCXMLVisitor可用于导出SCXML文档中的状态机定义。用户还可以调用StateMachine.exportXMLDefinition(true)导出美化的XML定义。
SCXMLVisitor visitor = SquirrelProvider.getInstance().newInstance(SCXMLVisitor.class);
stateMachine.accept(visitor);
visitor.convertSCXMLFile("MyStateMachine", true);

DotVisitor可以用来生成状态图,可以通过GraphViz查看。

DotVisitor visitor = SquirrelProvider.getInstance().newInstance(DotVisitor.class);
stateMachine.accept(visitor);
visitor.convertDotFile("SnakeStateMachine");
  • 状态机导入
    UntypedStateMachineImporter可用于导入由SCXMLVisitor或手写定义导出的状态机SCXML类似定义。UntypedStateMachineImporter将根据定义构建一个UntypedStateMachineBuilder,该定义以后可用于创建状态机实例。
UntypedStateMachineBuilder builder = new UntypedStateMachineImporter().importDefinition(scxmlDef);ATMStateMachine stateMachine = builder.newAnyStateMachine(ATMState.Idle);

注意:UntypedStateMachineImporter提供了XML样式来定义状态机,就像状态机构建器API或声明性注释一样。与SCXML类似的定义不等于标准SCXML。

  • 保存/加载状态机数据
    当状态机处于空闲状态时,用户可以保存状态机的数据。用户还可以将上面保存的数据加载到状态已终止或刚刚初始化的另一个状态机中.
    @Testpublic void testSavedData() {stateMachine.fire(LEvent.A12A2, 0);assertThat(stateMachine.getCurrentState(), equalTo(LState.A2));StateMachineData.Reader<TestStateMachine, LState, LEvent, Integer> savedData =stateMachine.dumpSavedData();assertThat(savedData.linkedStates(), contains(LState.A));stateMachine.terminate(null);try {// use bufferingOutputStream file = new FileOutputStream("data.sqr");OutputStream buffer = new BufferedOutputStream(file);OutputStreamWriter osw = new OutputStreamWriter(buffer, "UTF-8");osw.write(ObjectSerializableSupport.serialize(savedData));osw.flush();} catch (IOException ex) {Assert.fail();}setup();try {// use bufferingInputStream file = new FileInputStream("data.sqr");InputStream buffer = new BufferedInputStream(file);InputStreamReader isr = new InputStreamReader(buffer, "UTF-8");BufferedReader br = new BufferedReader(isr);String fileContent = br.readLine();// deserialize the ListStateMachineData.Reader<TestStateMachine, LState, LEvent, Integer> loadedSavedData =ObjectSerializableSupport.deserialize(fileContent);stateMachine.loadSavedData(loadedSavedData);stateMachine.fire(LEvent.A22A3, 0);assertThat(stateMachine.getCurrentState(), equalTo(LState.A3));} catch (Exception ex) {ex.printStackTrace();Assert.fail();}}
  • 状态机配置
    创建新的状态机实例时,用户可以通过StateMachineConfiguration来配置其行为 ,例如
UntypedStateMachine fsm = builder.newUntypedStateMachine("a", StateMachineConfiguration.create().enableAutoStart(false).setIdProvider(IdProvider.UUIDProvider.getInstance()), new Object[0]); // since 0.3.0fsm.fire(TestEvent.toA);

上面的示例代码用于创建一个以UUID作为其标识符的状态机实例,并禁用自动启动功能。
StateMachineConfigure也可以在状态机构建器上设置,这意味着由该配置创建builder.newStateMachine(S initialStateId)或builder.newStateMachine(S initialStateId, Object… extraParams)将使用此配置的所有状态机实例。

  • 状态机诊断

  • Timed State
    定时触发状态。定时任务将被提交给ScheduledExecutorService。用户可以通过SquirrelSingletonProvider注册您的ScheduledExecutorService实现实例,如果未注册ScheduledExecutorService实例,则SquirrelConfiguration将提供默认实例。之后,可以由状态机构建器定义定时状态。

  ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);SquirrelSingletonProvider.getInstance().register(ScheduledExecutorService.class, scheduler);builder.defineTimedState("A", 50, 100, "FIRST", null);builder.internalTransition().within("A").on("FIRST");
  • 子机状态
    将一个状态机作为另一个状态机的子状态。
public class LinkedStateMachineTest {enum LState {A, B, C, D, A1, A2, A3}enum LEvent {A2B, B2C, C2D, D2A, A12A2, A22A3, A32A1}@States({@State(name = "A", entryCallMethod = "enterA", exitCallMethod = "leftA"),@State(name = "B", entryCallMethod = "enterB", exitCallMethod = "leftB"),@State(name = "C", entryCallMethod = "enterC", exitCallMethod = "leftC"),@State(name = "D", entryCallMethod = "enterD", exitCallMethod = "leftD") })@Transitions({@Transit(from = "A", to = "B", on = "A2B", callMethod = "transitA2B"),@Transit(from = "B", to = "C", on = "B2C", callMethod = "transitB2C"),@Transit(from = "C", to = "D", on = "C2D", callMethod = "transitC2D"),@Transit(from = "D", to = "A", on = "D2A", callMethod = "transitD2A") })static class TestStateMachine extendsAbstractStateMachine<TestStateMachine, LState, LEvent, Integer> {private StringBuilder logger;protected TestStateMachine(StringBuilder logger) {this.logger = logger;}public void transitA2B(LState from, LState to, LEvent event,Integer context) {addOptionalDot();logger.append("transitA2B");}public void transitB2C(LState from, LState to, LEvent event,Integer context) {addOptionalDot();logger.append("transitB2C");}public void transitC2D(LState from, LState to, LEvent event,Integer context) {addOptionalDot();logger.append("transitC2D");}public void transitD2A(LState from, LState to, LEvent event,Integer context) {addOptionalDot();logger.append("transitD2A");}public void enterA(LState from, LState to, LEvent event, Integer context) {addOptionalDot();logger.append("enterA");}public void leftA(LState from, LState to, LEvent event, Integer context) {addOptionalDot();logger.append("leftA");}public void enterB(LState from, LState to, LEvent event, Integer context) {addOptionalDot();logger.append("enterB");}public void leftB(LState from, LState to, LEvent event, Integer context) {addOptionalDot();logger.append("leftB");}public void enterC(LState from, LState to, LEvent event, Integer context) {addOptionalDot();logger.append("enterC");}public void leftC(LState from, LState to, LEvent event, Integer context) {addOptionalDot();logger.append("leftC");}public void enterD(LState from, LState to, LEvent event, Integer context) {addOptionalDot();logger.append("enterD");}public void leftD(LState from, LState to, LEvent event, Integer context) {addOptionalDot();logger.append("leftD");}@Overridepublic void start(Integer context) {logger.append("start1");super.start(context);}@Overridepublic void terminate(Integer context) {addOptionalDot();logger.append("terminate1");super.terminate(context);}private void addOptionalDot() {if (logger.length() > 0) {logger.append('.');}}}@States({@State(name = "A1", entryCallMethod = "enterA1", exitCallMethod = "leftA1"),@State(name = "A2", entryCallMethod = "enterA2", exitCallMethod = "leftA2"),@State(name = "A3", entryCallMethod = "enterA3", exitCallMethod = "leftA3") })@Transitions({@Transit(from = "A1", to = "A2", on = "A12A2", callMethod = "transitA12A2"),@Transit(from = "A2", to = "A3", on = "A22A3", callMethod = "transitA22A3"),@Transit(from = "A3", to = "A1", on = "A32A1", callMethod = "transitA32A1") })static class LinkedStateMachine extendsAbstractStateMachine<LinkedStateMachine, LState, LEvent, Integer> {private StringBuilder logger;protected LinkedStateMachine(StringBuilder logger) {this.logger = logger;}public void transitA12A2(LState from, LState to, LEvent event,Integer context) {logger.append("transitA12A2");}public void transitA22A3(LState from, LState to, LEvent event,Integer context) {logger.append("transitA22A3");}public void transitA32A1(LState from, LState to, LEvent event,Integer context) {logger.append("transitA32A1");}public void enterA1(LState from, LState to, LEvent event,Integer context) {logger.append("enterA1");}public void leftA1(LState from, LState to, LEvent event, Integer context) {logger.append("leftA1");}public void enterA2(LState from, LState to, LEvent event,Integer context) {logger.append("enterA2");}public void leftA2(LState from, LState to, LEvent event, Integer context) {logger.append("leftA2");}public void enterA3(LState from, LState to, LEvent event,Integer context) {logger.append("enterA3");}public void leftA3(LState from, LState to, LEvent event, Integer context) {logger.append("leftA3");}@Overrideprotected void beforeActionInvoked(LState from, LState to, LEvent event, Integer context) {addOptionalDot();}@Overridepublic void start(Integer context) {addOptionalDot();logger.append("start2");super.start(context);}@Overridepublic void terminate(Integer context) {addOptionalDot();logger.append("terminate2");super.terminate(context);}private void addOptionalDot() {if (logger.length() > 0) {logger.append('.');}}}TestStateMachine stateMachine;TestStateMachine stateMachine2;StringBuilder logger;@Beforepublic void setup() {logger = new StringBuilder();StateMachineBuilder<LinkedStateMachine, LState, LEvent, Integer> builderOfLinkedStateMachine = StateMachineBuilderFactory.create(LinkedStateMachine.class, LState.class, LEvent.class,Integer.class, new Class<?>[] { StringBuilder.class });StateMachineBuilder<TestStateMachine, LState, LEvent, Integer> builderOfTestStateMachine = StateMachineBuilderFactory.create(TestStateMachine.class, LState.class, LEvent.class,Integer.class, new Class<?>[] { StringBuilder.class });// 定义链接状态builderOfTestStateMachine.defineLinkedState(LState.A, builderOfLinkedStateMachine, LState.A1, logger);builderOfTestStateMachine.defineLinkedState(LState.C, builderOfLinkedStateMachine, LState.A2, logger);stateMachine = builderOfTestStateMachine.newStateMachine(LState.A, logger);stateMachine2 = builderOfTestStateMachine.newStateMachine(LState.A, logger);}@Testpublic void testInitialLinkedState() {doTestInitialLinkedState(stateMachine, logger);logger.append("|");doTestInitialLinkedState(stateMachine2, logger);assertThat(logger.toString(), equalTo("start1.enterA.start2.enterA1|start1.enterA.start2.enterA1"));}private void doTestInitialLinkedState(TestStateMachine stateMachine, StringBuilder logger) {stateMachine.start(0);assertThat(stateMachine.getCurrentState(), equalTo(LState.A1));assertThat(stateMachine.getCurrentRawState().getStateId(), equalTo(LState.A1));}@Testpublic void testLinkedStateMachineProcessEvent() {stateMachine.fire(LEvent.A12A2, 0);assertThat(logger.toString(),equalTo("start1.enterA.start2.enterA1.leftA1.transitA12A2.enterA2"));}@Testpublic void testTestStateMachineProcessEvent() {stateMachine.fire(LEvent.A2B, 0);assertThat(logger.toString(),equalTo("start1.enterA.start2.enterA1.terminate2.leftA1.leftA.transitA2B.enterB"));}@Testpublic void testInitialLinkedState2() {stateMachine.fire(LEvent.A2B, 0);System.out.println(logger);stateMachine.fire(LEvent.B2C, 0);System.out.println(logger);System.out.println(stateMachine.getCurrentState());stateMachine.fire(LEvent.A22A3, 0);System.out.println(logger);assertThat(stateMachine.getCurrentState(), equalTo(LState.A3));assertThat(stateMachine.getCurrentRawState().getStateId(), equalTo(LState.A3));}
}

Squirrel State Machine相关推荐

  1. 有限状态机FSM(Finite State Machine)及实现方式介绍(转)

    原文:https://www.cnblogs.com/barrywxx/p/12860573.html 一.为什么引入有限状态机? 最近做一个项目,项目中很多实体(Entity),每个实体都有很多状态 ...

  2. 【翻译】What is State Machine Diagram(什么是状态机图)?

    [翻译]What is State Machine Diagram(什么是状态机图)? 写在前面 在上一篇学习类图的时候将这个网站上的类图的一篇文章翻译了出来,感觉受益良多,今天来学习UML状态机图, ...

  3. Spring State Machine:它是什么,您需要它吗?

    状态机是基于有限状态的计算模型 ,正如Wikipedia非常明确地说的那样. 通常,工作流会与状态一起使用,这意味着您不能仅从任何状态进入任何其他状态:应遵循一些规则. 这些状态之间的转换受规则限制. ...

  4. Android系统自带的层次状态机StateMachine(Hierarchical State Machine)

    Android系统自带的层次状态机StateMachine(Hierarchical State Machine) Android在framework层自己实现一套层次状态机,总共有三个类:State ...

  5. 有限状态机FSM(finite state machine) 二

    有限状态机FSM(finite state machine) 二 延续上一篇继续有限状态机 上一篇中的状态切换判断是在每一个状态类的 OnExecute 方法中各种 if else 硬编码逻辑 当状态 ...

  6. FSM(Finite State Machine,有限状态机)设计

    有限状态机(Finite State Machine, FSM),根据状态机的输出是否与输入有关,可分为Moore型状态机和Mealy型状态机.Moore型状态机输出仅仅与现态有关和Mealy型状态机 ...

  7. 《计算机组成与CPU设计实验》5有限状态机的Verilog HDL描述(Finite State Machine,FSM)

    多数控制逻辑都可以用有限状态机描述 状态机 状态机是组合逻辑和时序逻辑的特殊组合 时序逻辑用于存储状态 组合逻辑用于产生次态和产生输出 状态的数量是有限的,故称为有限状态机(Finite State ...

  8. Mina State machine状态机讲解

    原文地址:Mina State machine(Apache Mina User guide Chapter14 State machine) 如果您使用的是Mina与复杂网络开发应用程序交互,你可能 ...

  9. Android官方实现的层次状态机Hierarchical State Machine源代码

    Android官方内部的源代码中实现了一套层次状态机(Hierarchical State Machine),总共有三个代码文件:IState.java , State.java, StateMach ...

最新文章

  1. 端口01 - 零基础入门学习汇编语言67
  2. 强烈安利8个高质量的办公软件,提高你的办公效率
  3. 学习笔记(二十二)—— 了解进程和线程
  4. mysql中字符串拼接函数_MySQL字符串连接函数
  5. 50 FI配置-财务会计-固定资产-与总账集成-定义集成资产购置的技术清算科目
  6. vue v2.5.0源码-双向数据绑定
  7. LeetCode 84. 柱状图中最大的矩形(Largest Rectangle in Histogram)
  8. net core 小坑杂记之配置文件读取(不定期更新)
  9. Mac Pro 安装 Sublime Text 3,个性化设置,主题 和 插件 收藏
  10. 19. 删除链表的倒数第N个节点【双指针经典应用】详解
  11. 一步一步安装 Windows Server 2008 Beta3(Code Name Longhorn)
  12. 使用EasyCHM生成CHM文档
  13. [转载]使用 Abbot 框架自动化测试 Eclipse 插件的用户界面,第 2 部分
  14. PSF 点扩展函数 (from WikiPedia)
  15. TF卡和SD卡的区别
  16. 商业网站建设和运营的四度:Approachability、Usability、 Accessibility 和 Profitability...
  17. android.permission.camera,Android - revoked permission android.permission.CAMERA
  18. [-Flutter趣玩篇-] 出神入化的Align+动画
  19. 【PCL模块解析 05 之KDTree】01 KDTree原理及代码解析
  20. 资料:SAP所有模块用户出口(User Exits)

热门文章

  1. 亚马逊云科技re:Invent 2022 Ruba Borno主题演讲
  2. 苹果手机屏幕尺寸、密度、开发尺寸、像素尺寸、倍图
  3. 7-35 城市间紧急救援 (25 分)
  4. 装nvida显卡驱动后循环登录 闪退的方法UBUNTU16.04
  5. [UFUN函数] UG二次开发,设置渲染样式,例如带边着色、静态线框等
  6. 大卫·鲍伊(David Bowie)在AR中:Planeta如何通过Unity打造杀手级应用
  7. 如何监控和改进用于深度学习的 GPU 使用率?
  8. Python 学习书籍推荐
  9. 作者:陈跃国(1978-),男,中国人民大学信息学院副教授,博士生导师。
  10. AttributeError: module 'requests' has no attribute 'get'错误解析