JS設計模式六:策略模式

策略模式簡述

策略模式定義一系列的算法,把它們一個個封裝起來,并且使它們可以相互替換。

策略模式的優(yōu)點:
一、策略模式可以有效避免很多if條件語句
二、策略模式符合開放-封閉原則,使代碼更容易理解和擴展
三、策略模式中的代碼可以復用

實戰(zhàn)一

以公司年終獎為例:
一、績效為A的人,年終獎為工資的4倍
二、績效為B的人,年終獎為工資的3倍
三、績效為C的人,年終獎為工資的2倍

傳統(tǒng)的解決方案

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 函數(shù)包含了很多if-else語句。
二、calculateBouns 函數(shù)缺乏彈性,假如還有D等級的話,那么我們需要在calculateBouns 函數(shù)內(nèi)添加判斷等級D的if語句;
三、算法復用性差,如果在其他的地方也有類似這樣的算法的話,但是規(guī)則不一樣,我們這些代碼不能通用。

使用組合函數(shù)重構代碼

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 函數(shù)有可能會越來越大,比如增加D等級的時候,而且缺乏彈性。

使用策略模式重構代碼

策略模式指的是定義一系列的算法,把它們一個個封裝起來,將不變的部分和變化的部分隔開,實際就是將算法的使用和實現(xiàn)分離出來。

一個基于策略模式的程序至少由2部分組成,第一個部分是一組策略類,策略類封裝了具體的算法,并負責具體的計算過程。第二個部分是環(huán)境類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

實戰(zhàn)二

表單檢驗是非常常見的功能。因為涉及到大量的驗證規(guī)則,使用策略模式會非常便利。
代碼如下,關鍵是領會精神,實現(xiàn)細節(jié)不細說~~~

// 策略對象
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 = [];  // 保存效驗規(guī)則
};
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(); // 創(chuàng)建一個Validator對象
    /* 添加一些效驗規(guī)則 */
    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;
    }
}
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容