策略模式與狀態模式不是雙胞胎,而是情侶!

老姚發表於2019-08-05

今天說說搞物件這件事情兒。

我們經常愛問一個人,你為啥還單著?

對方的回答無非是如下這兩種:

  • 沒遇到合適的。
  • 太忙了,沒有時間。

其他回答,要麼能歸於這二者其一,要麼二者兼顧。

然而,在我看來,這二者分別對應了策略模式和狀態模式。

使用後臺語言的同學都知道策略模式和狀態模式是對雙胞胎,只有出生之後才分開。

又或說二者長得十分像,但是性格迥然不同。

我認為這種說法沒有說到點子上,準確地說二者是情侶,一男一女。

1. 策略模式

那麼什麼是策略模式?

策略、策略,講究的是做一件事情可以有不同的招數。

所以很多書籍都愛用“錦囊妙計”來說它。

var doSomething1 = function() {
  console.log('xxx');
};
var doSomething2 = function() {
  console.log('yyy');
}
// 核心
var doSomething = function(strategy) {
  if (strategy == 'xxx') doSomething1();
  if (strategy == 'yyy') doSomething2();
};
doSomething('xxx'); // xxx
doSomething('yyy'); // yyy
複製程式碼

上面的程式碼就是策略的一種 if-else 實現方式。

在前端使用可以如下實現策略模式:

var doSomething = function(strategy) {
  strategys[strategy]();
};
var strategys = {
  xxx: function() {
    console.log('xxx');
  },
  yyy: function() {
    console.log('yyy');
  }
};
doSomething('xxx'); // xxx
doSomething('yyy'); // yyy
複製程式碼

策略模式,你傳什麼,我就使用什麼招數!

2. 狀態模式

策略模式的分析暫告一段落,我們再來看看什麼是狀態?

狀態、狀態,今天沒心情上班,此心情就是狀態。

之前看過一個段子:

A:來了?
B:來了。
A:來了?
B:來了。
A:來嗎?
B:不來了。

這個段子的含義是,能不能“來”,取決於當前的狀態。

一個具體例子,開關,它最能體現出狀態。

var state = 'off';
var doSomething1 = function() {
  if (state == 'off') {
    console.log('doSomething1 and turn to on');
    flag = 'on';
  }
  if (state == 'on') {
    console.log('doSomething1 else');
  }
};
var doSomething2 = function() {
  if (state == 'off') {
    console.log('doSomething2');
  }
  if (state == 'on') {
    console.log('doSomething2 else and turn to off');
    flag = 'off';
  }
}

doSomething1(); // doSomething1 and turn to on
doSomething1(); // doSomething1 else
doSomething2(); // doSomething2 else and turn to off
doSomething2(); // doSomething2
複製程式碼

每次去做事情時,結果是取決於當前的狀態的。

上述邏輯改成狀態模式實現:

var doSomething1 = function () {
  state.doSomething1();
};
var doSomething2 = function () {
  state.doSomething2();
};
var off = {
  doSomething1: function () {
    console.log('doSomething1 and turn to on');
    state = on;
  },
  doSomething2: function () {
    console.log('doSomething2');
  }
}
var on = {
  doSomething1: function () {
    console.log('doSomething1 else');
  },
  doSomething2: function () {
    console.log('doSomething2 else and turn to off');
    state = off;
  }
}
var state = off
doSomething1(); // doSomething1 and turn to on
doSomething1(); // doSomething1 else
doSomething2(); // doSomething2 else and turn to off
doSomething2(); // doSomething2
複製程式碼

ok,這就是狀態指導行為。

3. 情侶關係

策略模式和狀態模式是什麼以及如何簡單實現,應該相對清楚了。

使用相應模式後,程式碼變得清晰了,也容易應對變化。

可以新增不同的策略,可以新增不同的狀態。

現在我們來看看他倆為啥是情侶關係?

策略模式根據外界條件來選取不同的策略

狀態模式根據內部狀態來決定不同的反應

"有象斯有對,對必反其為"。

一個外,一個內。

這兩句看起來是對仗工整。但是看二者程式碼,卻沒有這麼覺得呢?

發現策略模式程式碼量小,而狀態模式程式碼量大,後者幾乎是前者的兩倍。

說二者是男女,策略應該是男的,而狀態是女的。

男的關心的是如何快速解決問題,拿出解決方法。

女人關心的是當前心情和情緒的安撫,關注內在狀態。

從上面的程式碼量來看,女生想的心事兒比較多。

下面讓例子程式碼量對等一下。

這裡用策略模式來嘗試模擬你的技能和興趣。

var 絕技 = {
  思考: function () {
    console.log("胡思亂想");
  },
  看書: function() {
    console.log('一氣呵成');
  }
};

var 愛好 = {
  吹牛: function () {
    console.log("牛上天了");
  },
  抽菸: function() {
    console.log("騰雲駕霧");
  }
};

var 你 = {
  展示絕技: function(strategy) {
    絕技[strategy]();  
  },
  展示愛好: function(strategy) {
    愛好[strategy]();
  }
};

你.展示絕技("思考"); // 胡思亂想
你.展示絕技("看書"); // 一氣呵成
你.展示愛好("吹牛"); // 牛上天了
你.展示愛好("抽菸"); // 騰雲駕霧
複製程式碼

上述程式碼封裝了兩組演算法,每組演算法內由外界來決定選擇具體某種演算法。

那麼對於狀態模式,也來寫一下自己。

var 煩 = {
  吹牛: function() {
    console.log('吹一吹,心情大爽啊');
    當前心情 = 爽;
  },
  抽菸: function() {
    console.log('心情不好的時候,越抽越沒勁');
  }
};

var 爽 = {
  吹牛: function() {
    console.log('越吹越爽');
  },
  抽菸: function() {
    console.log('一想起吸菸有害健康,開始不爽起來');
    當前心情 = 煩;
  }
};

var 當前心情 = 煩;

var 老姚 = {
  吹牛: function() {
    當前心情["吹牛"]();
  },
  抽菸: function() {
    當前心情["抽菸"]();
  }
};
老姚.吹牛(); // 吹一吹,心情大爽啊
老姚.吹牛(); // 越吹越爽
老姚.抽菸(); // 一想起吸菸有害健康,開始不爽起來
老姚.抽菸(); // 心情不好的時候,越抽越沒勁
複製程式碼

狀態模式是封裝一個個狀態,狀態封裝所有行為,具體某個行為,由當前的狀態來決定。

現在程式碼量等同了。有看出了一種對偶關係了嗎?

策略模式:定義了一系列的演算法,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化。

狀態模式:允許一個物件在其內部狀態改變時改變它的行為。物件看起來似乎修改了它的類。

二者定義裡,都有“不同”這個詞語。

有象斯有對,對必反其為。

策略模式取決於傳進來的策略。

狀態取決於上一次呼叫後,當前的狀態。

但是,策略模式好理解。也很好應用。宛如一個少年,沒啥心思。

狀態模式,我覺得就比較屌了。

對於一個複雜的過程,狀態模式才能發揮真正實力。

關鍵你如何去劃分狀態,構造出狀態機。

看來女人不只是半邊天那麼簡單。

對於狀態模式的使用,讓我想起一個故事。

說是有一位精神病人,跑到屋裡,把門從裡面反鎖。

然後大聲對屋外喊著,我要把你們鎖進裡面,永遠都別想出去!!


不知道我有沒有說清楚,希望有所幫助。

也歡迎閱讀本人的《JS正則迷你書》

本文完。

相關文章