状态模式
相关组件有状态(State),事件(Event),动作(Action),状态机(ActionContext)。
通过红绿灯可以获得一个demo:
有三种状态:红色,绿色,黄色;
有一种事件:灯改变事件;
有三种动作:红变绿,绿变黄,黄变红;
State
标识状态。
package fsm;
/**
* @author wenei
* @date 2021-11-11 20:42
*/
public abstract class State {
public String getName() {
return this.getClass().getSimpleName();
}
@Override
public String toString() {
return getName() + "{}";
}
}
Event
表示事件。
package fsm;
/**
* @author wenei
* @date 2021-11-11 20:42
*/
public abstract class Event {
public String getName() {
return this.getClass().getSimpleName();
}
@Override
public String toString() {
return getName() + "{}";
}
}
Action
表示动作,在指定的State下,发生指定Event便会调用Action进行操作,并返回下一状态。
package fsm;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* @author wenei
* @date 2021-11-11 20:42
*/
public abstract class Action<S extends State, E extends Event> {
public Class<?> getStateType() {
return (Class<?>) getGenericType(0);
}
public Class<?> getEventType() {
return (Class<?>) getGenericType(1);
}
private Type getGenericType(int i) {
return ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[i];
}
/**
* 处理state状态时发生的event事件
* @param state 当前状态
* @param event 发生的事件
* @return 下一状态
*/
public abstract State handle(S state, E event);
@Override
public String toString() {
return this.getClass().getSimpleName() + "{" + getStateType().getSimpleName()
+ "," + getEventType().getSimpleName() +
"}";
}
}
ActionContext
整个Action的上下文,也就是状态机。
package fsm;
import java.util.ArrayList;
import java.util.List;
/**
* @author wenei
* @date 2021-11-11 20:49
*/
public class ActionContext {
private State currentState;
private List<Action> actions = new ArrayList<>();
public ActionContext(State currentState) {
this.currentState = currentState;
}
public void addAction(Action action) {
actions.add(action);
}
public ActionContext handle(Event event) {
for (Action action : actions) {
if (action.getEventType().isInstance(event) && action.getStateType().isInstance(currentState)) {
currentState = action.handle(currentState, event);
break;
}
}
return this;
}
@Override
public String toString() {
return "ActionContext{" +
"currentState=" + currentState +
", actions=" + actions +
'}';
}
}
测试
相关实现
红绿灯状态的转变。
GreenAction,RedAction,YellowAction类似。
package fsm.action;
import fsm.Action;
import fsm.State;
import fsm.event.ChangeEvent;
import fsm.state.GreenState;
import fsm.state.YellowState;
/**
* @author wenei
* @date 2021-11-11 20:53
*/
public class GreenAction extends Action<GreenState, ChangeEvent> {
@Override
public State handle(GreenState state, ChangeEvent event) {
System.out.println("GreenAction:" + state + "," + event);
return new YellowState();
}
}
RedState,YellowState,GreenState类似
package fsm.state;
import fsm.State;
/**
* @author wenei
* @date 2021-11-11 20:52
*/
public class GreenState extends State {
}
ChangeEvent:改变事件
package fsm.event;
import fsm.Event;
/**
* @author wenei
* @date 2021-11-11 20:52
*/
public class ChangeEvent extends Event {
}
Test
package fsm;
import fsm.action.GreenAction;
import fsm.action.RedAction;
import fsm.action.YellowAction;
import fsm.event.ChangeEvent;
import fsm.state.RedState;
/**
* @author wenei
* @date 2021-11-11 20:55
*/
public class Test {
public static void main(String[] args) {
ActionContext context = new ActionContext(new RedState());
context.addAction(new RedAction());
context.addAction(new GreenAction());
context.addAction(new YellowAction());
System.out.println(context);
context.handle(new ChangeEvent());
System.out.println(context);
context.handle(new ChangeEvent());
System.out.println(context);
context.handle(new ChangeEvent());
System.out.println(context);
}
}
/*
ActionContext{currentState=RedState{}, actions=[RedAction{RedState,ChangeEvent}, GreenAction{GreenState,ChangeEvent}, YellowAction{YellowState,ChangeEvent}]}
RedAction:RedState{},ChangeEvent{}
ActionContext{currentState=GreenState{}, actions=[RedAction{RedState,ChangeEvent}, GreenAction{GreenState,ChangeEvent}, YellowAction{YellowState,ChangeEvent}]}
GreenAction:GreenState{},ChangeEvent{}
ActionContext{currentState=YellowState{}, actions=[RedAction{RedState,ChangeEvent}, GreenAction{GreenState,ChangeEvent}, YellowAction{YellowState,ChangeEvent}]}
YellowAction:YellowState{},ChangeEvent{}
ActionContext{currentState=RedState{}, actions=[RedAction{RedState,ChangeEvent}, GreenAction{GreenState,ChangeEvent}, YellowAction{YellowState,ChangeEvent}]}
*/