需求
初始状态下,【暂停按钮】不可点,所有数轴可调:
点击【动态波】后,【暂停按钮】可点,所有数轴可调:
点击【暂停按钮】后,“暂停”变为“播放”,所有数轴不可调:
分析需求
上面的需求很明显可以分为三个状态:初始状态、波动状态、暂停状态。不同的状态下,同一个按钮的表现不一样,比如暂停按钮,在初始状态下不可点,在其它状态下可点。
其实判断是否使用状态模式也是这样考虑:看同一个对象,在整个生命周期中,对同一个事件是否有多种响应。如果有的话,那这个对象就存在多个状态。如果多个对象都有某几个状态(比如都有播放,暂停状态),那就可以考虑使用状态模式了。
使用状态模式的好处是,可以消除分散各处的状态判断的代码。
实现代码
- 不使用状态模式:
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){
//...
}
}
这样,每个状态下该做什么,一目了然。