JS 狀態模式

SHERlocked93發表於2017-12-20

1. 簡介

狀態模式(State)允許一個物件在其內部狀態改變的時候改變它的行為,物件看起來似乎修改了它的類。
其實就是用一個物件或者陣列記錄一組狀態,每個狀態對應一個實現,實現的時候根據狀態挨個去執行實現。

2. 實現

比如超級瑪麗,就可能同時有好幾個狀態比如 跳躍,移動,射擊,蹲下 等,如果對這些動作一個個進行處理判斷,需要多個if-else或者switch不僅醜陋不說,而且在遇到有組合動作的時候,實現就會變的更為複雜,這裡可以使用狀態模式來實現。

狀態模式的思路是:首先建立一個狀態物件或者陣列,內部儲存狀態變數,然後內部封裝好每種動作對應的狀態,然後狀態物件返回一個介面物件,它可以對內部的狀態修改或者呼叫。

const SuperMarry = (function() {    
  let _currentState = [],        // 狀態陣列
      states = {
        jump() {console.log('跳躍!')},
        move() {console.log('移動!')},
        shoot() {console.log('射擊!')},
        squat() {console.log('蹲下!')}
      }
  
  const Action = {
    changeState(arr) {  // 更改當前動作
      _currentState = arr
      return this
    },
    goes() {
      console.log('觸發動作')
      _currentState.forEach(T => states[T] && states[T]())
      return this
    }
  }
  
  return {
    change: Action.changeState,
    go: Action.goes
  }
})()

SuperMarry
    .change(['jump', 'shoot'])
    .go()                    // 觸發動作  跳躍!  射擊!
    .go()                    // 觸發動作  跳躍!  射擊!
    .change(['squat'])
    .go()                    // 觸發動作  蹲下!

這裡可以使用ES6class優化一下:

class SuperMarry {
  constructor() {
    this._currentState = []
    this.states = {
      jump() {console.log('跳躍!')},
      move() {console.log('移動!')},
      shoot() {console.log('射擊!')},
      squat() {console.log('蹲下!')}
    }
  }
  
  change(arr) {  // 更改當前動作
    this._currentState = arr
    return this
  }
  
  go() {
    console.log('觸發動作')
    this._currentState.forEach(T => this.states[T] && this.states[T]())
    return this
  }
}

new SuperMarry()
    .change(['jump', 'shoot'])
    .go()                    // 觸發動作  跳躍!  射擊!
    .go()                    // 觸發動作  跳躍!  射擊!
    .change(['squat'])
    .go()                    // 觸發動作  蹲下!

3. 總結

狀態模式的使用場景也特別明確,有如下兩點:

  1. 一個物件的行為取決於它的狀態,並且它必須在執行時刻根據狀態改變它的行為。
  2. 一個操作中含有大量的分支語句,而且這些分支語句依賴於該物件的狀態。狀態通常為一個或多個列舉常量的表示。

簡而言之,當遇到很多同級if-else或者switch的時候,可以使用狀態模式來進行簡化。


本文是系列文章,可以相互參考印證,共同進步~

  1. JS 抽象工廠模式
  2. JS 工廠模式
  3. JS 建造者模式
  4. JS 原型模式
  5. JS 單例模式
  6. JS 回撥模式
  7. JS 外觀模式
  8. JS 介面卡模式
  9. JS 利用高階函式實現函式快取(備忘模式)
  10. JS 狀態模式
  11. JS 橋接模式
  12. JS 觀察者模式

網上的帖子大多深淺不一,甚至有些前後矛盾,在下的文章都是學習過程中的總結,如果發現錯誤,歡迎留言指出~

參考:
《Javascript 設計模式》 - 張榮銘
設計模式之狀態模式

相關文章