状态机
(State Machine)是一种用于描述系统在不同状态下的行为及状态之间转换的数学模型。状态机主要由三个部分组成:状态
(State)、事件
(Event)和转换
(Transition)。
相关资料:有限状态机 - 维基百科,自由的百科全书 (wikipedia.org)
如下图所示,整个状态机包含5个节点,每个节点都有自己对应的逻辑,每个节点都可能执行多次
下面代码为上面图片的参考demo代码
//状态枚举
enum StateEnum {
//定义开始节点以及结束节点,便于状态流转控制
Start("doProcessA", new DoProcessA()),
ProcessB("doProcessB", new DoProcessB()),
ProcessC("doProcessC", new DoProcessC()),
ProcessD("doProcessD", new DoProcessD()),
End("", null);
private String stateClassName;
private State state;
StateEnum(String stateClassName, State doProcessAClass) {
this.stateClassName = stateClassName;
this.state = doProcessAClass;
}
public String getStateClassName() {
return this.stateClassName;
}
public void setStateClassName(final String stateClassName) {
this.stateClassName = stateClassName;
}
public State getState() {
return this.state;
}
public void setState(final State state) {
this.state = state;
}
}
//状态信息上下文
class StateContext {
private List<String> processList;
private static Map<String, State> statesMap = new ConcurrentHashMap<>();
/**
* 创建上下文
* @return
*/
public static StateContext createStateContext() {
StateContext stateContext = new StateContext();
stateContext.setProcessList(new ArrayList<>());
return stateContext;
}
/**
* 获取具体状态执行器
* @param name
* @return
*/
public static State getStateByName(StateEnum name) {
if (statesMap.size() == 0) {
for (StateEnum value : StateEnum.values()) {
if (!StateEnum.End.equals(value)){
statesMap.put(value.getStateClassName(), value.getState());
}
}
}
if (StateEnum.End.equals(name)) {
return null;
} else {
return statesMap.get(name.getStateClassName());
}
}
public List<String> getProcessList() {
return this.processList;
}
public void setProcessList(final List<String> processList) {
this.processList = processList;
}
}
//抽象状态节点接口
interface State {
void doProcess(StateContext stateContext);
StateEnum nextState(StateContext stateContext);
}
//具体状态实现节点DoProcessA、DoProcessB、DoProcessC、DoProcessD
class DoProcessA implements State{
@Override
public void doProcess(StateContext stateContext) {
System.out.println("processing A...");
List<String> processList = stateContext.getProcessList();
processList.add("process a");
System.out.println("current processList:" + processList);
}
@Override
public StateEnum nextState(StateContext stateContext) {
return StateEnum.ProcessB;
}
}
class DoProcessB implements State{
@Override
public void doProcess(StateContext stateContext) {
System.out.println("processing B...");
List<String> processList = stateContext.getProcessList();
processList.add("process b");
System.out.println("current processList:" + processList);
}
@Override
public StateEnum nextState(StateContext stateContext) {
//处理分支分叉
if (null != stateContext.getProcessList() && stateContext.getProcessList().size() <= 3){
return StateEnum.ProcessD;
}
return StateEnum.ProcessC;
}
}
class DoProcessC implements State{
@Override
public void doProcess(StateContext stateContext) {
System.out.println("processing C...");
List<String> processList = stateContext.getProcessList();
processList.add("process c");
System.out.println("current processList:" + processList);
}
@Override
public StateEnum nextState(StateContext stateContext) {
return StateEnum.End;
}
}
class DoProcessD implements State{
@Override
public void doProcess(StateContext stateContext) {
System.out.println("processing D...");
List<String> processList = stateContext.getProcessList();
processList.add("process d");
System.out.println("current processList:" + processList);
}
@Override
public StateEnum nextState(StateContext stateContext) {
return StateEnum.ProcessB;
}
}
//测试demo
public class StateTest {
public static void main(String[] args) {
StateContext stateContext = StateContext.createStateContext();
//定义开始节点
StateEnum stateEnum = StateEnum.Start;
State state = StateContext.getStateByName(stateEnum);
do {
//处理业务
state.doProcess(stateContext);
//设置下一个状态节点
StateEnum nextStateEnum = state.nextState(stateContext);
state = StateContext.getStateByName(nextStateEnum);
//节点执行到结束节点后,状态机停止运行
}while (!StateEnum.End.equals(stateEnum) && null != state);
System.out.println("process end");
}
}
状态机在处理具有复杂状态转换逻辑的场景时非常有用。以下是一些适用状态机的典型场景:
状态机适用于那些具有多个状态及状态之间存在复杂转换关系的场景。通过使用状态机,可以将复杂的逻辑分解为多个简单的状态,使代码更加易于理解和维护。