[TOC]
# 策略模式
定義一系列的算法,把它們一個個的封裝起來,并且使它們可以相互替換。目的就是算法的使用和算法的實現分離出來。
由兩部分組成:
- 策略類:封裝了具體的算法,并負責具體的計算過程
- 環境類:接受客戶的請求,隨后把請求委托給某一個策略類
## 面向對象的實現
```javascript
var S = function(){};
S.prototype.calculate = function(salary){
return salary * 4;
}
var A = function(){};
A.prototype.calculate = function(salary){
return salary * 3;
}
var B = function(){};
B.prototype.calculate = function(salary){
return salary * 2;
}
var Bouns = function(){
this.salary = null;
this.strategy = null;
}
Bouns.prototype.setSalary = function(salary){
this.salary = salary
}
Bouns.prototype.setStrategy = function(strategy){
this.strategy = strategy;
}
Bouns.prototype.getBouns = function(){
return this.strategy.calculate(this.salary);
}
var bouns = new Bouns();
bouns.setSalary(1000);
bouns.setStrategy(new B()); // 設置策略對象
bouns.getBouns();// 輸出
```
## JavaScript中的實現
```javascript
var Strategy = {
S: function(salary){
return salary * 4;
},
A: function(salary){
return salary * 3;
},
B: function(salary){
return salary * 2;
}
};
var getBouns = function(strategy, salary){
return Strategy[strategy](salary);
}
getBouns('B', 1000); // 2000
```
## 多態在策略模式中的體現
環境類并沒有計算的能力,而是將計算委托給了策略類,會返回不同的計算結果,也正是多態的表現,也是“它們可以相互替換”的目的。
## 更廣義的“算法”
策略模式可以用來封裝一系列的“業務規則”,只要這些業務規則指向的目標一致,并且可以被替換使用,我們就可以用策略模式來封裝它們。比如表單校驗。
## 表單校驗
```javascript
var strategies = {
isNonEmpty: function(value, errorMsg){
....
},
minLength: function(value, length, errorMsg){
....
},
isMobile: function(value, errorMsg){
...
}
};
var Validator = function(){
this.cache = [];
};
Validator.prototype.add = function(dom, rule, errorMsg){
var ary = [rule];
this.cache.push(function(){
var strategy = ary.shift();
ary.unshift(dom.value);
ary.push(errorMsg);
return strategies[strategy].apply(dom, ary);
});
}
Validator.prototype.start = function(){
for(var i=0, validatorFunc; validatorFunc = this.cache[i++]){
var msg = validatorFunc();
if(msg){
return msg;
}
}
}
var validatorFunc = function(){
var validator = new Validator(); // 創建一個對象
validator.add(...);
var errorMsg = validator.start(); // 獲取校驗結果
}
var registerForm = document.getElementById('form');
registerForm.onsubmit = function(){
var errorMsg = validatorFunc();
if(errorMsg){
return false;
}
}
```
## 策略模式的優缺點
1. 避免多重條件選擇語句
2. 將算法獨立在策略類中,使得它們易于切換、易于理解、易于擴展
3. 策略類可以用在系統的其它地方中
4. 策略類可以利用組合和委托來讓環境類擁有執行算法的能力,這也是繼承的一種更輕便的替代方案