状态机,在程序员方面,常用于多种状态和多种事件下,优化程序的美观可读性。
否则可能会频繁使用 if else 等判断语句,使得代码杂乱。
具体描述可访问:https://www.jianshu.com/p/403f750e1d3a
状态机类编写,可直接复制使用。
export default class FSM {
/**上个状态 */
private _curState: number;
/**下个状态 */
private _preState: number;
//[state]=>callback
private _stateMap: {[state: number]:(...args)=>any};
//[event][fromState]=>toState
private _eventMap: {[event: number]: {[fromState: number]: number}};
constructor(defaultState: number){
this._stateMap = {};
this._eventMap = {};
this._curState = this._preState = defaultState;
}
/**增加状态回调 */
public addState(state: number, callback: (...args)=>any){
if (this.isContainState(state)){
console.log("error", "FSM 重复addState state:" + state);
return ;
}
this._stateMap[state] = callback;
}
public setState(state: number, callback: (...args)=>any){
this._stateMap[state] = callback;
}
/**增加事件,事件发生后,从fromState状态变为toState状态 */
public addEvent(event: number, fromState: number, toState: number){
if (!this.isContainState(fromState)){
console.log("error", "FSM addEvent 不存在state from:" + fromState);
return;
}
if (!this.isContainState(toState)){
console.log("error", "FSM addEvent 不存在state to:" + fromState);
return;
}
if (this._eventMap[event] == null){
this._eventMap[event] = {};
}
this._eventMap[event][fromState] = toState;
}
/**执行事件 */
public doEvent(event: number, ...args){
if (this.canDoEvent(event)){
return this.changeToState(this._eventMap[event][this._curState], ...args);
}
}
private canDoEvent(event: number){
return this._eventMap[event] != null && this._eventMap[event][this._curState] != null;
}
public isContainState(state: number): boolean{
return this._stateMap[state] != null;
}
private changeToState(state: number, ...args): any{
if (!this.isContainState(state)){
console.log("error", "FSM changeToState 不存在state: " + state);
return ;
}
this._preState = this._curState;
this._curState = state;
return this._stateMap[state](...args);
}
/**获得当前状态 */
public getCurState(): number{
return this._curState;
}
/**获取上次状态 */
public getPreState(): number{
return this._preState;
}
}
-----------------------------使用的例子-------------------------------
/**事件 */
export const enum FSMEvent{
/**起床 */
GET_UP,
/**步行 */
WALK,
/**回房间 */
BACK_ROOM,
}
/**状态 */
export const enum FSMState{
NONE,
/**准备上班 */
PREPARING,
/**工作中 */
WORKING,
/**回家 */
COME_BACK_HOME,
/**睡觉中 */
SLEEPING,
}
//初始为睡觉状态
let fsm = new FSM(FSMState.SLEEPING);
//增加当前状态需要干的事情
fsm.addState(FSMState.PREPARING, () => {
console.log("刷牙洗脸。");
//步行去上班
fsm.doEvent(FSMEvent.WALK);
});
fsm.addState(FSMState.WORKING, () => {
console.log("8个小时过去了,也该下班了。");
//步行回家
fsm.doEvent(FSMEvent.WALK);
});
fsm.addState(FSMState.COME_BACK_HOME, () => {
console.log("回到家了,在家里看电视。");
//回房间
fsm.doEvent(FSMEvent.BACK_ROOM);
});
fsm.addState(FSMState.SLEEPING, () => {
console.log("在房间睡觉。");
//起床
fsm.doEvent(FSMEvent.GET_UP);
});
//增加事件,起床事件 睡觉中状态 => 准备上班
fsm.addEvent(FSMEvent.GET_UP, FSMState.SLEEPING, FSMState.PREPARING);
//增加事件,步行事件 准备上班 => 工作中
fsm.addEvent(FSMEvent.WALK, FSMState.PREPARING, FSMState.WORKING);
//增加事件,步行事件 工作中 => 回家
fsm.addEvent(FSMEvent.WALK, FSMState.WORKING, FSMState.COME_BACK_HOME);
//增加事件,回房间事件 回家 => 睡觉中
fsm.addEvent(FSMEvent.BACK_ROOM, FSMState.COME_BACK_HOME, FSMState.SLEEPING);
/**
* 整个事件流程:
* 睡觉中 => 起床 => 准备上班 => 步行 => 工作中 => 步行 => 回家 => 回房间 => 睡觉中
*/