JavaScript設計模式三(策略模式)
策略模式定義
定義一系列算法,把他們一個個封裝起來吨拗,并且使他們相互替換
我們可以先看一個例子
策略模式計算年終獎
大家知道年終獎的發(fā)放是和工資基數和年終考評來計算的算柳,例如A是4個月工資媒役,B是3個月工資偿曙,C是2個月工資龙亲。
1、最初的代碼實現
var calculateBonus = function(level, salary) {
if (level === 'A') {
return salary*4;
}
if (level === 'B') {
return salary*3;
}
if (level === 'C') {
return salary*2;
}
}
使用方法:
calcaluteBonus('B', 10000)
這段代碼平常我們見到的很多恳不,但是它有著明顯的缺點
- 函數很雜,隨著業(yè)務邏輯的增加开呐,這個函數會越來越大
- 缺乏彈性烟勋,例如我們A的考評變成5倍,或者增加D的考評筐付,必須要去修改這個函數卵惦,這里是違反了開發(fā)-封閉原則
- 算法不存在復用性,例如我們需要再另外一個函數中使用這些算法瓦戚,需要重新再寫一遍
2沮尿、利用組合函數重構代碼
簡單來解釋,就是把那些算法封裝到一個個函數里面。
var algorithmA = function(salary) {
return salary*4;
}
var algorithmB = function(salary) {
return salary*3;
}
var algorithmC = funtion(salary) {
return salary*2;
}
var calculateBonus = function(level, salary) {
if (level === 'A') {
return algorithmA(salary);
}
if (level === 'B') {
return algorithmB(salary*3);
}
if (level === 'C') {
return algorithmC(salary*2);
}
}
這么修改之后畜疾,這些算法我們可以在其他函數里面復用了赴邻,但是還是沒有解決calculateBonus函數龐大的問題。
3啡捶、使用策略模式重構代碼
一個策略模式的程序至少由兩部分組成
- 一組策略類姥敛,也就是算法,這些策略類會封裝算法瞎暑,并且負責具體的計算規(guī)則
- 環(huán)境上下文彤敛,接受客戶的請求,然后把請求委托給某一個策略類了赌。因此在這個上下文中要維持對某一個策略對象的引用墨榄。
我們先看一個模仿面向對象語言的實現:
// 策略類
var algorithmA = function(){}
algorithmA.prototype.calculate = function(salary) {
return salary*4;
}
var algorithmB = function(){}
algorithmB.prototype.calculate = function(salary) {
return salary*3;
}
var algorithmB = function(){}
algorithmB.prototype.calculate = function(salary) {
return salary*2;
}
// 環(huán)境上下文
var Bonus = function(){
this.salary = null;
this.strategy = null;
}
Bonus.prototype.setSalary = function(salary) {
this.salary = salary;
}
Bonus.prototype.setStrategy = function(strategy) {
this.strategy = strategy;
}
Bonus.prototype.getBonus = function() {
return this.strategy.calculate( this.salary );
}
// 使用
var bonus = new Bonus();
bonus.setSalary(10000);
bonus.setStrategy(new algorithmA());
console.log(bonus.getBonus());
剛才上面說到了面向對象的的實現,但是其實我們很少會這樣寫勿她,我們看看JavaScript的版本
4渠概、JavaScript版本的策略模式
var strategies = {
"A": function(salary) {
return salary*4;
},
"B": function(salary) {
return salary*3;
},
"C": function(salary) {
return salary*2;
},
};
var calculateBonus = function(level, salary) {
return strategies[level](salary);
};
calculateBonus('A', 10000);
驚不驚喜,意不意外嫂拴,就是這么簡單播揪。
策略模式更加廣義的用法
上面我們說的策略模式封裝的是算法,但是實際上我們不僅僅可以封裝算法筒狠,還可以封裝一些業(yè)務規(guī)則猪狈,例如表單驗證里面,我們可以封裝不同的校驗邏輯辩恼,這里就不舉例說明了雇庙,如果有興趣可以參考JavaScript設計模式與實踐這本書
策略模式的優(yōu)缺點
優(yōu)點:
- 策略模式利用組合、委托和多態(tài)的技術和思想灶伊,能夠有效的避免多重條件選擇語句
- 策略模式符合開發(fā)-封閉原則疆前,把算法封裝在獨立的strategy中,讓算法利于切換聘萨、理解和擴展
- 策略模式的算法能夠很方便的在其他地方復用
- 策略模式利用組合和委托讓環(huán)境上下文有執(zhí)行算法的能力竹椒,這也是繼承的一種體現
缺點:
- 策略模式需要在代碼中增加許多策略類或者策略對象
- 要使用好策略模式的前提是:必須了解所有的strategy,并且知道他們之間的不同點米辐,這是違反最少知識原則的胸完。