概念:
State:状态
Event:事件,状态由事件触发,引起变化
Transition:流转,表示从一个状态到另一个状态
External Transition:外部流转,两个不同状态之间的流转
Internal Transition:内部流转,同一个状态之间的流转
Condition:条件,表示是否允许到达某个状态
Action:动作,到达某个状态之后,可以做什么
StateMachine:状态机
外部状态转移的test用例:
过程描述:起始状态STATE1,结束状态STATE2,当发生EVENT1时执行状态转移,当满足checkCondition()时,执行doAction,执行成功则返回状态STATE2,否则返回STATE1。
@Test
public void testExternalNormal(){
// 第一步:生成一个状态机builder
StateMachineBuilder<States, Events, Context> builder = StateMachineBuilderFactory.create();
// 第二步:设置一个外部状态转移类型的builder,并设置from\to\on\when\perform
builder.externalTransition()
.from(States.STATE1)
.to(States.STATE2)
.on(Events.EVENT1)
.when(checkCondition())
.perform(doAction());
// 第三步:设置状态机的id和ready,并在StateMachineFactory中的stateMachineMap进行注册
StateMachine<States, Events, Context> stateMachine = builder.build(MACHINE_ID);
// 第四步:触发状态机
States target = stateMachine.fireEvent(States.STATE1, Events.EVENT1, new Context());
Assert.assertEquals(States.STATE2, target);
}
1. 第一步:
- StateMachineBuilderFactory.create()
public class StateMachineBuilderFactory {
// 创建了一个StateMachineBuilderImpl实例对象
public static <S, E, C> StateMachineBuilder<S, E, C> create(){
return new StateMachineBuilderImpl<>();
}
}
2. 第二步:
- builder.externalTransition()
public class StateMachineBuilderImpl<S, E, C> implements StateMachineBuilder<S, E, C> {
/**
* StateMap is the same with stateMachine, as the core of state machine is holding reference to states.
*/
private final Map<S, State< S, E, C>> stateMap = new ConcurrentHashMap<>();
...
// 创建了一个TransitionBuilderImpl对象,并传入空的stateMap(状态表),类型为EXTERNAL
@Override
public ExternalTransitionBuilder<S, E, C> externalTransition() {
return new TransitionBuilderImpl<>(stateMap, TransitionType.EXTERNAL);
}
...
}
new TransitionBuilderImpl<>(stateMap, TransitionType.EXTERNAL)
class TransitionBuilderImpl<S,E,C> implements ExternalTransitionBuilder<S,E,C>, InternalTransitionBuilder<S,E,C>, From<S,E,C>, On<S,E,C>, To<S,E,C> {
final Map<S, State<S, E, C>> stateMap;
...
final TransitionType transitionType;
// 把状态表和状态机类型赋给本地变量
public TransitionBuilderImpl(Map<S, State<S, E, C>> stateMap, TransitionType transitionType) {
this.stateMap = stateMap;
this.transitionType = transitionType;
}
...
}
-
.from(States.STATE1)、.to(States.STATE2)
class TransitionBuilderImpl<S,E,C> implements ExternalTransitionBuilder<S,E,C>, InternalTransitionBuilder<S,E,C>, From<S,E,C>, On<S,E,C>, To<S,E,C> {
final Map<S, State<S, E, C>> stateMap;
private State<S, E, C> source;
protected State<S, E, C> target;
...
// 此时只是把from的state新增到stateMap中,返回结果赋给本地变量source
@Override
public From<S, E, C> from(S stateId) {
source = StateHelper.getState(stateMap, stateId);
return this;
}
// 此时只是把to的state新增到stateMap中,返回结果赋给本地变量target
@Override
public To<S, E, C> to(S stateId) {
target = StateHelper.getState(stateMap, stateId);
return this;
}
...
}
StateHelper.getState
public class StateHelper {
// 根据stateId获取state,如果不存在则插入stateMap
public static <S, E, C> State<S, E, C> getState(Map<S, State<S, E, C>> stateMap, S stateId){
State<S, E, C> state = stateMap.get(stateId);
if (state == null) {
state = new StateImpl<>(stateId);
stateMap.put(stateId, state);
}
return state;
}
}
-
.on(Events.EVENT1)
on条件:source包含transition,transition包含event、target、transitionType
class TransitionBuilderImpl<S,E,C> implements ExternalTransitionBuilder<S,E,C>, InternalTransitionBuilder<S,E,C>, From<S,E,C>, On<S,E,C>, To<S,E,C> {
final Map<S, State<S, E, C>> stateMap;
private State<S, E, C> source;
protected State<S, E, C> target;
private Transition<S, E, C> transition;
final TransitionType transitionType;
...
@Override
public On<S, E, C> on(E event) {
transition = source.addTransition(event, target, transitionType);
return this;
}
...
}
source.addTransition(event, target, transitionType)
public class StateImpl<S,E,C> implements State<S,E,C> {
protected final S stateId;
private HashMap<E, Transition<S, E,C>> transitions = new HashMap<>();
StateImpl(S stateId){
this.stateId = stateId;
}
// 新增一个transition(状态转移对象)插入本地Map transitions中
@Override
public Transition<S, E, C> addTransition(E event, State<S,E,C> target, TransitionType transitionType) {
Transition<S, E, C> newTransition = new TransitionImpl<>();
newTransition.setSource(this);
newTransition.setTarget(target);
newTransition.setEvent(event);
newTransition.setType(transitionType);
Debugger.debug("Begin to add new transition: "+ newTransition);
verify(event, newTransition);
transitions.put(event, newTransition);
return newTransition;
}
/**
* Per one source and target state, there is only one transition is allowed
* @param event
* @param newTransition
*/
private void verify(E event, Transition<S,E,C> newTransition) {
Transition existingTransition = transitions.get(event);
if(existingTransition != null){
if(existingTransition.equals(newTransition)){
throw new StateMachineException(existingTransition+" already Exist, you can not add another one");
}
}
}
}
- .when(checkCondition())
设置transition的condition
class TransitionBuilderImpl<S,E,C> implements ExternalTransitionBuilder<S,E,C>, InternalTransitionBuilder<S,E,C>, From<S,E,C>, On<S,E,C>, To<S,E,C> {
...
@Override
public When<S, E, C> when(Condition<C> condition) {
transition.setCondition(condition);
return this;
}
}
checkCondition()
public interface Condition<C> {
/**
* @param context context object
* @return whether the context satisfied current condition
*/
boolean isSatisfied(C context);
default String name(){
return this.getClass().getSimpleName();
}
}
private Condition<Context> checkCondition() {
return (ctx) -> {return true;};
}
- .perform(doAction())
设置transition的action
class TransitionBuilderImpl<S,E,C> implements ExternalTransitionBuilder<S,E,C>, InternalTransitionBuilder<S,E,C>, From<S,E,C>, On<S,E,C>, To<S,E,C> {
...
@Override
public void perform(Action<S, E, C> action) {
transition.setAction(action);
}
}
doAction()
public interface Action<S, E, C> {
public void execute(S from, S to, E event, C context);
}
private Action<States, Events, Context> doAction() {
return (from, to, event, ctx)->{
System.out.println(ctx.operator+" is operating "+ctx.entityId+" from:"+from+" to:"+to+" on:"+event);
};
}
第三步:
- builder.build(MACHINE_ID)
public class StateMachineBuilderImpl<S, E, C> implements StateMachineBuilder<S, E, C> {
...
private final StateMachineImpl<S, E, C> stateMachine = new StateMachineImpl<>(stateMap);
...
// 设置状态机的id和ready,并在StateMachineFactory中的stateMachineMap进行注册
@Override
public StateMachine<S, E, C> build(String machineId) {
stateMachine.setMachineId(machineId);
stateMachine.setReady(true);
StateMachineFactory.register(stateMachine);
return stateMachine;
}
}
public class StateMachineFactory {
static Map<String /* machineId */, StateMachine> stateMachineMap = new ConcurrentHashMap<>();
// 将状态机插入stateMachineMap,判断machineId是否重复
public static <S, E, C> void register(StateMachine<S, E, C> stateMachine){
String machineId = stateMachine.getMachineId();
if(stateMachineMap.get(machineId) != null){
throw new StateMachineException("The state machine with id ["+machineId+"] is already built, no need to build again");
}
stateMachineMap.put(stateMachine.getMachineId(), stateMachine);
}
}
第四步:
-
stateMachine.fireEvent(States.STATE1, Events.EVENT1, new Context())
public class StateMachineImpl<S,E,C> implements StateMachine<S, E, C> {
private String machineId;
private final Map<S, State<S,E,C>> stateMap;
private boolean ready;
public StateMachineImpl(Map<S, State< S, E, C>> stateMap){
this.stateMap = stateMap;
}
// 触发状态机
public S fireEvent(S sourceStateId, E event, C ctx){
isReady();
State sourceState = getState(sourceStateId);
return doTransition(sourceState, event, ctx).getId();
}
// 执行转移
private State<S, E, C> doTransition(State sourceState, E event, C ctx) {
Optional<Transition<S,E,C>> transition = sourceState.getTransition(event);
if(transition.isPresent()){
return transition.get().transit(ctx);
}
Debugger.debug("There is no Transition for " + event);
return sourceState;
}
// 根据stateId获取状态机当前state
private State getState(S currentStateId) {
State state = StateHelper.getState(stateMap, currentStateId);
if(state == null){
showStateMachine();
throw new StateMachineException(currentStateId + " is not found, please check state machine");
}
return state;
}
// 判断状态机是否准备完毕
private void isReady() {
if(!ready){
throw new StateMachineException("State machine is not built yet, can not work");
}
}
...
}
sourceState.getTransition(event)
public class StateImpl<S,E,C> implements State<S,E,C> {
protected final S stateId;
private HashMap<E, Transition<S, E,C>> transitions = new HashMap<>();
...
// 根据event获取transition(转移对象)
@Override
public Optional<Transition<S, E, C>> getTransition(E event) {
return Optional.ofNullable(transitions.get(event));
}
...
}
transition.get().transit(ctx)
test用例中作者对于Condition和Action的实现类简单处理了,实际使用时应该分别实现这两个接口中的方法。
public class TransitionImpl<S,E,C> implements Transition<S,E,C> {
private State<S, E, C> source;
private State<S, E, C> target;
private E event;
private Condition<C> condition;
private Action<S,E,C> action;
private TransitionType type = TransitionType.EXTERNAL;
...
// 执行转移,如果满足condition,则执行action,并返回状态targe,否则返回状态source
@Override
public State<S, E, C> transit(C ctx) {
Debugger.debug("Do transition: "+this);
this.verify();
if(condition == null || condition.isSatisfied(ctx)){
if(action != null){
action.execute(source.getId(), target.getId(), event, ctx);
}
return target;
}
Debugger.debug("Condition is not satisfied, stay at the "+source+" state ");
return source;
}
// 如果是内部转移类型,source必须等于target
@Override
public void verify() {
if(type== TransitionType.INTERNAL && source != target) {
throw new StateMachineException(String.format("Internal transition source state '%s' " +
"and target state '%s' must be same.", source, target));
}
}
}
多个外部状态转移的test用例:
和单个的起始状态的差别不大,只是builder在维护source和transition是map
@Test
public void testExternalTransitionsNormal(){
StateMachineBuilder<States, Events, Context> builder = StateMachineBuilderFactory.create();
builder.externalTransitions()
.fromAmong(States.STATE1, States.STATE2, States.STATE3)
.to(States.STATE4)
.on(Events.EVENT1)
.when(checkCondition())
.perform(doAction());
StateMachine<States, Events, Context> stateMachine = builder.build(MACHINE_ID+"1");
States target = stateMachine.fireEvent(States.STATE2, Events.EVENT1, new Context());
Assert.assertEquals(States.STATE4, target);
}
内部状态转移的test用例:
外部状态转移唯一的差别在于from和to的state是同一个。
@Test
public void testInternalNormal(){
StateMachineBuilder<States, Events, Context> builder = StateMachineBuilderFactory.create();
builder.internalTransition()
.within(States.STATE1)
.on(Events.INTERNAL_EVENT)
.when(checkCondition())
.perform(doAction());
StateMachine<States, Events, Context> stateMachine = builder.build(MACHINE_ID+"2");
stateMachine.fireEvent(States.STATE1, Events.EVENT1, new Context());
States target = stateMachine.fireEvent(States.STATE1, Events.INTERNAL_EVENT, new Context());
Assert.assertEquals(States.STATE1, target);
}