基本概念
有限状态机FSM
描述事物的有限状态机模型的元素由以下组成:
- 状态(State):事物的状态,包括初始状态和所有事件触发后的状态
- 事件(Event):触发状态变化或者保持原状态的事件
- 行为或转换(Action/Transition):执行状态转换的过程
- 检测器(Guard):检测某种状态要转换成另一种状态的条件是否满足
状态机的要素
状态机可归纳为4个要素,即现态、条件、动作、次态。“现态”和“条件”是因,“动作”和“次态”是果。详解如下:
1. 现态:是指当前所处的状态。
2. 条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
3. 动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
4. 次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。
代码实现
定义状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public enum ProcessState {
INIT(0, "未开始"),
READY_ONE_SIDE(1, "一方准备完成"),
READY_ALL(2, "双方准备完成"),
CHAT(3, "发言完成"),
END(4, "结束"),
;
private int val;
private String desc;
ProcessState(int val, String desc) {
this.val = val;
this.desc = desc;
}
public int getVal() {
return val;
}
}定义事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public enum ProcessEvent {
READY_ONE_SIDE(1, "一方准备"),
READY_ALL(2, "另一方准备"),
CHAT(3, "发言"),
FORBID_ALL(4, "全员禁言"),
;
private Integer code;
private String desc;
ProcessEvent(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public Integer getCode() {
return code;
}
}定义状态机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public class ProcessEventConfig {
private ProcessEvent event;
private ProcessState fromState;
private ProcessState toState;
public String desc(){
return fromState.getDesc() + "_" + event.getDesc() + "_" + toState.getDesc();
}
}
List<ProcessEventConfig> configList = new ArrayList<>(16);
configList.add(new ProcessEventConfig(ProcessEvent.READY_ONE_SIDE, ProcessState.INIT, ProcessState.READY_ONE_SIDE));
configList.add(new ProcessEventConfig(ProcessEvent.READY_ALL, ProcessState.READY_ONE_SIDE, ProcessState.READY_ALL));
configList.add(new ProcessEventConfig(ProcessEvent.CHAT, ProcessState.READY_ALL, ProcessState.CHAT));
configList.add(new ProcessEventConfig(ProcessEvent.FORBID_ALL, ProcessState.CHAT, ProcessState.END));
Map<ProcessEvent, ProcessEventConfig> eventResultStateConfigMap = new EnumMap<>(ProcessEvent.class);
configList.forEach(eventConfig -> eventResultStateConfigMap.put(eventConfig.getEvent(), eventConfig));触发状态变化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public boolean fire(ProcessEvent event, Process process) {
ProcessEventConfig config = Optional.ofNullable(eventResultStateConfigMap.get(event)).orElseThrow(() -> ExceptionCodeEnum.AGRS_INVALID.newException("不存在该事件"));
if (process.getStatus() != config.getFromState().getVal()) {
return false;
}
process.setRemark(config.desc());
process.setStatus(config.getToState().getVal());
//DB改变状态
/*update table set status=${status} WHERE id={id} AND status=${beforeStatus}*/
boolean suc = processManager.updateStatus(process, config.getFromState().getVal());
if (suc) {
//变更成功,业务逻辑
}
return suc;
}