這裡有一份簡潔的前端知識體系等待你查收,看看吧,會有驚喜哦~如果覺得不錯,懇求star哈~
策略模式簡述
策略模式定義一系列的演算法,把它們一個個封裝起來,並且使它們可以相互替換。
策略模式的優點: 一、策略模式可以有效避免很多if條件語句 二、策略模式符合開放-封閉原則,使程式碼更容易理解和擴充套件 三、策略模式中的程式碼可以複用
實戰一
以公司年終獎為例: 一、績效為A的人,年終獎為工資的4倍 二、績效為B的人,年終獎為工資的3倍 三、績效為C的人,年終獎為工資的2倍
傳統的解決方案
var calculateBouns = function(salary,level) {
if(level === 'A') {
return salary * 4;
}
if(level === 'B') {
return salary * 3;
}
if(level === 'C') {
return salary * 2;
}
};
// 呼叫如下:
console.log(calculateBouns(4000,'A')); // 16000
console.log(calculateBouns(2500,'B')); // 7500
複製程式碼
如上程式碼,存在的缺陷有: 一、calculateBouns 函式包含了很多if-else語句。 二、calculateBouns 函式缺乏彈性,假如還有D等級的話,那麼我們需要在calculateBouns 函式內新增判斷等級D的if語句; 三、演算法複用性差,如果在其他的地方也有類似這樣的演算法的話,但是規則不一樣,我們這些程式碼不能通用。
使用組合函式重構程式碼
var performanceA = function(salary) {
return salary * 4;
};
var performanceB = function(salary) {
return salary * 3;
};
var performanceC = function(salary) {
return salary * 2
};
var calculateBouns = function(level,salary) {
if(level === 'A') {
return performanceA(salary);
}
if(level === 'B') {
return performanceB(salary);
}
if(level === 'C') {
return performanceC(salary);
}
};
// 呼叫如下
console.log(calculateBouns('A',4500)); // 18000
複製程式碼
程式碼看起來有點改善,但是還是有如下缺點:calculateBouns 函式有可能會越來越大,比如增加D等級的時候,而且缺乏彈性。
使用策略模式重構程式碼
策略模式指的是定義一系列的演算法,把它們一個個封裝起來,將不變的部分和變化的部分隔開,實際就是將演算法的使用和實現分離出來。
一個基於策略模式的程式至少由2部分組成,第一個部分是一組策略類,策略類封裝了具體的演算法,並負責具體的計算過程。第二個部分是環境類Context,該Context接收客戶端的請求,隨後把請求委託給某一個策略類。
var obj = {
"A": function(salary) {
return salary * 4;
},
"B" : function(salary) {
return salary * 3;
},
"C" : function(salary) {
return salary * 2;
}
};
var calculateBouns =function(level,salary) {
return obj[level](salary);
};
console.log(calculateBouns('A',10000)); // 40000
複製程式碼
實戰二
表單檢驗是非常常見的功能。因為涉及到大量的驗證規則,使用策略模式會非常便利。 程式碼如下,關鍵是領會精神,實現細節不細說~~~
// 策略物件
var strategys = {
isNotEmpty: function(value,errorMsg) {
if(value === '') {
return errorMsg;
}
},
// 限制最小長度
minLength: function(value,length,errorMsg) {
if(value.length < length) {
return errorMsg;
}
},
// 手機號碼格式
mobileFormat: function(value,errorMsg) {
if(!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
return errorMsg;
}
}
};
var Validator = function(){
this.cache = []; // 儲存效驗規則
};
Validator.prototype.add = function(dom,rules) {
var self = this;
for(var i = 0, rule; rule = rules[i++]; ){
(function(rule){
var strategyAry = rule.strategy.split(":");
var errorMsg = rule.errorMsg;
self.cache.push(function(){
var strategy = strategyAry.shift();
strategyAry.unshift(dom.value);
strategyAry.push(errorMsg);
return strategys[strategy].apply(dom,strategyAry);
});
})(rule);
}
};
Validator.prototype.start = function(){
for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {
var msg = validatorFunc(); // 開始效驗 並取得效驗後的返回資訊
if(msg) {
return msg;
}
}
};
// 程式碼呼叫
var registerForm = document.getElementById("registerForm");
var validateFunc = function(){
var validator = new Validator(); // 建立一個Validator物件
/* 新增一些效驗規則 */
validator.add(registerForm.userName,[
{strategy: 'isNotEmpty',errorMsg:'使用者名稱不能為空'},
{strategy: 'minLength:6',errorMsg:'使用者名稱長度不能小於6位'}
]);
validator.add(registerForm.password,[
{strategy: 'minLength:6',errorMsg:'密碼長度不能小於6位'},
]);
validator.add(registerForm.phoneNumber,[
{strategy: 'mobileFormat',errorMsg:'手機號格式不正確'},
]);
var errorMsg = validator.start(); // 獲得效驗結果
return errorMsg; // 返回效驗結果
};
// 點選確定提交
registerForm.onsubmit = function(){
var errorMsg = validateFunc();
if(errorMsg){
alert(errorMsg);
return false;
}
}
複製程式碼