需求
初始狀態下,【暫停按鈕】不可點,所有數軸可調:
點擊【動態波】後,【暫停按鈕】可點,所有數軸可調:
點擊【暫停按鈕】後,“暫停”變爲“播放”,所有數軸不可調:
分析需求
上面的需求很明顯可以分爲三個狀態:初始狀態、波動狀態、暫停狀態。不同的狀態下,同一個按鈕的表現不一樣,比如暫停按鈕,在初始狀態下不可點,在其它狀態下可點。
其實判斷是否使用狀態模式也是這樣考慮:看同一個對象,在整個生命週期中,對同一個事件是否有多種響應。如果有的話,那這個對象就存在多個狀態。如果多個對象都有某幾個狀態(比如都有播放,暫停狀態),那就可以考慮使用狀態模式了。
使用狀態模式的好處是,可以消除分散各處的狀態判斷的代碼。
實現代碼
- 不使用狀態模式:
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){
//...
}
}
這樣,每個狀態下該做什麼,一目瞭然。