做某些业务逻辑时使用状态机可以将不同的功能分到各个各个及业务的阶段去写,避免了某一个文件功能繁多,代码冗杂的 问题 ,便于阅读及后续维护
BaseState 定义一个状态基类,各个业务逻辑继承这个基类 其中定义两个方法 分别是进入当前状态 和退出当前状态时触发的事件 onStateEnter onStateExit
StateMachine 状态机
其中 registerState removeState 用来注册和 删除状态,调用changeState方法 会触发baseState里定义的onStateEnter onStateExit
使用:创建一个状态继承BaseState 重写 onStateEnter onStateExit方法 用来初始化/清除进入当前状态时的数据
调用StateMachine 的registerState注册状态
调用StateMachine的changeState方法触发进入当前状态
1、定义状态基类 BaseSate.ts
type ChangeFunc = {(stateName: string | number, extraInfo: any | null, exitCallback: Function, enterCallback: Function): void}
export default class BaseState {
private NAME: string | number; //状态名
private isRunning: boolean; //当前状态是否在运行
public changeState: ChangeFunc; //定义一个改变状态的方法
constructor(name: string | number) {
this.NAME = name;
this.isRunning = false
}
public getIsRunning() {
return this.isRunning
}
public setIsRunning(isRunning: boolean = false){
this.isRunning = isRunning
}
public getStateName() {
return this.NAME
}
public onStateEnter(extraInfo: any = null, fromeState: string|number = "", callback: Function = null) {
callback && callback()
}
public onStateExit(extrainfo: any = null, nextState: string|number = "", callback: Function = null) {
callback && callback()
}
}
2、状态机
/*
* @FilePath: StateMachine.ts
* @Author: wanghj
* @Date: 2022-07-22 10:20:26
* @LastEditTime: 2022-07-22 17:49:35
* Copyright: 2022 All Rights Reserved.
* @Descripttion: 状态机
*/
import { Dic } from "../common/Dic";
import BaseState from "./BaseState";
enum CannotChangeReason {
None = 0,
SameState = 1,
NotRegist = 2,
}
export default class StateMachine {
private states: Dic<BaseState>;
private currentState: any;
constructor() {
this.states = new Dic<BaseState>()
this.currentState = null;
}
public getCurrentState() {
return this.currentState
}
public registerState(stateName: string | number, state: BaseState) {
if (typeof(stateName) == "number") {
stateName = stateName.toString()
}
if(stateName == null || null == state) {
return false
}
if(this.states.get(stateName)) {
return false
}
this.states.put(stateName, state)
state.changeState = this.changeState
return true
}
public removeState(stateName: string | number) {
if (stateName == null) {
return false
}
if (typeof(stateName) == "number") {
stateName = stateName.toString()
}
if (this.states.get(stateName) == null) {
return false
}
this.states.remove(stateName)
return true
}
public clearState() {
let keys = this.states.keys()
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
this.removeState(key)
}
this.states = new Dic<BaseState>()
}
public hasState(stateName: string | number) {
if (stateName == null) {
return false
}
if (typeof(stateName) == "number") {
stateName = stateName.toString()
}
return this.states.containsKey(stateName)
}
public getState(stateName: string | number) {
if (stateName == null) {
return null
}
if (typeof(stateName) == "number") {
stateName = stateName.toString()
}
return this.states.get(stateName)
}
public changeState(stateName: string | number, extraInfo: any = null, exitCallback: Function = null, enterCallback: Function = null) {
if (stateName == null ) {
return false
}
let cannotchangeReason = this.getCannotChangeReason(stateName)
if(cannotchangeReason != CannotChangeReason.None) {
return false
}
this._changeState(stateName, extraInfo, exitCallback, enterCallback)
return true
}
public exitCurrentState() {
if (this.currentState) {
this.currentState.setIsRunning(false)
this.currentState.onStateExit()
this.currentState = null
}
}
private _changeState(stateName: string | number, extraInfo: any, exitCallback: Function = null, enterCallback: Function = null) {
let currentState = this.getCurrentState()
let currentStateName = currentState.getStateName()
let destState = this.getState(stateName)
currentState.setIsRunning(false)
currentState.onStateExit(extraInfo, stateName, exitCallback)
destState.setIsRunning(true)
destState.onStateEnter(extraInfo, stateName, enterCallback)
}
private getCannotChangeReason(stateName) {
if (this.hasState(stateName) == false) {
return CannotChangeReason.NotRegist
}
if (this.getCurrentState() && this.getCurrentState().getStateName() == stateName) {
return CannotChangeReason.SameState
}
return CannotChangeReason.None
}
}