狀態模式

定義

允許一個對象在其內部狀態改變時改變它的行為,對象看起來似乎修改了它的類。

要點

  • 狀態模式的關鍵是區分事物內部的狀態,事物內部狀態的改變往往會帶來事物的行為改變。把事物的每種狀態都封裝成單獨的類,跟此種狀態有關的行為都封裝在這個類的內部。
  • 在主體類(Context)的構造函數裡為每個狀態類都創建一個狀態對象。主體對象不再執行任何實質性的操作,而是把請求委託給當前所處的狀態的對象去執行。
  • 狀態模式可以避免 Context 無限膨脹,狀態切換的邏輯被分佈在狀態類中,去掉了 Context 中原本過多的條件分支。
  • 缺少抽象類的變通方式:讓父類的方法直接拋出一個異常,這個異常會在程序運行期間被發現。
  • 狀態模式的缺點是邏輯分散在狀態類中,雖然避開了不受歡迎的條件分支語句,但也造成了邏輯分散的問題,我們無法在一個地方就看出整個狀態機的邏輯。
  • 狀態模式和策略模式:它們都有一個上下文、一些狀態或者策略類,上下文把請求委託給這些類來執行。它們的區別是策略模式中的各個策略類是平行的,互相之間沒有聯繫,用戶使用前需要知道所有策略類的作用;狀態模式中,狀態對應的行為以及狀態之間的切換是已經規定好的,「改變行為」只發生在狀態模式內部,用戶是不需要瞭解這些細節的。
  • JavaScript 中可以通過 Function.prototype.call 方式非常方便地使用委託技術,並不需要事先讓一個對象持有另一個對象的引用。
  • 表驅動的有限狀態機

核心代碼

var Light = function() {
    this.currState = FSM.off;
    this.button = null;
};

Light.prototype.init = function() {
    var self = this;
    var button = document.createElement('button');
    this.button = button;
    // ...
    this.button.onclick = function() {
        self.currState.buttonWasPressed.call(self);
    };
};

var FSM = {
    off: {
        buttonWasPressed: function() {
            // ...
            this.currState = FSM.on;
        }
    },
    on: {
        buttonWasPressed: function() {
            // ...
            this.currState = FSM.off;
        }
    }
};
var delegate = function(client, delegation) {
    return {
        buttonWasPressed: function() {
            return delegation.buttonWasPressed.apply(client, arguments);
        }
    }
};

var Light = function() {
    this.button = null;
    this.offState = delegate(this, FSM.off);    
    this.onState = delegate(this, FSM.on);
    this.currState = this.offState;
};

Light.prototype.init = function() {
    var self = this;
    // ...
    this.button.onclick = function() {
        self.currState.buttonWasPressed();
    };
};

你可能感兴趣的:(狀態模式)