需求
初始状态下,【暂停按钮】不可点,所有数轴可调:
点击【动态波】后,【暂停按钮】可点,所有数轴可调:
点击【暂停按钮】后,“暂停”变为“播放”,所有数轴不可调:
分析需求
上面的需求很明显可以分为三个状态:初始状态、波动状态、暂停状态。不同的状态下,同一个按钮的表现不一样,比如暂停按钮,在初始状态下不可点,在其它状态下可点。
其实判断是否使用状态模式也是这样考虑:看同一个对象,在整个生命周期中,对同一个事件是否有多种响应。如果有的话,那这个对象就存在多个状态。如果多个对象都有某几个状态(比如都有播放,暂停状态),那就可以考虑使用状态模式了。
使用状态模式的好处是,可以消除分散各处的状态判断的代码。
实现代码
- 不使用状态模式:
class DomEvent{stop(e){if(this.state === 'waving'){//处理波动状态}else if(this.state === 'stop'){//处理暂停状态}else{//处理初始状态}}/*** 点击波长数轴*/clickWave(e){if(this.state === 'stop'){return;}//...}
}
- 使用状态模式
export default class DomEvent{//单例static _inst;static getInst(){DomEvent._inst = DomEvent._inst || new DomEvent();return DomEvent._inst;}constructor(){}init(){this.stateList = {"default" : new DefaultState(),"waving" : new WavingState(),"stop" : new StopState()}this.state = this.stateList["default"];return this;}/*** 修改状态*/changeState(stateName){this.state = this.stateList[stateName];}stop(e){this.state.stop(e);}/*** 点击波长数轴*/clickWave(e){this.state.clickWave(e);}
}
具体的状态类可以这样写:
export default class StopState{constructor(){this.domEvents = DomEvent.getInst();}stop(e){this.stopBtn.text("播放");this.domEvents.changeState('waving');}/*** 点击波长数轴*/clickWave(e){//...}
}
这样,每个状态下该做什么,一目了然。