狀態模式案例分析

需求

初始狀態下,【暫停按鈕】不可點,所有數軸可調:

這裏寫圖片描述

點擊【動態波】後,【暫停按鈕】可點,所有數軸可調:

這裏寫圖片描述

點擊【暫停按鈕】後,“暫停”變爲“播放”,所有數軸不可調:

這裏寫圖片描述

分析需求

上面的需求很明顯可以分爲三個狀態:初始狀態、波動狀態、暫停狀態。不同的狀態下,同一個按鈕的表現不一樣,比如暫停按鈕,在初始狀態下不可點,在其它狀態下可點。

其實判斷是否使用狀態模式也是這樣考慮:看同一個對象,在整個生命週期中,對同一個事件是否有多種響應。如果有的話,那這個對象就存在多個狀態。如果多個對象都有某幾個狀態(比如都有播放,暫停狀態),那就可以考慮使用狀態模式了。

使用狀態模式的好處是,可以消除分散各處的狀態判斷的代碼。

實現代碼

  • 不使用狀態模式:
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){
        //...
    }
}

這樣,每個狀態下該做什麼,一目瞭然。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章