今天說說搞物件這件事情兒。
我們經常愛問一個人,你為啥還單著?
對方的回答無非是如下這兩種:
- 沒遇到合適的。
- 太忙了,沒有時間。
其他回答,要麼能歸於這二者其一,要麼二者兼顧。
然而,在我看來,這二者分別對應了策略模式和狀態模式。
使用後臺語言的同學都知道策略模式和狀態模式是對雙胞胎,只有出生之後才分開。
又或說二者長得十分像,但是性格迥然不同。
我認為這種說法沒有說到點子上,準確地說二者是情侶,一男一女。
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正則迷你書》。
本文完。