Javascript设计模式学习三(策略模式)

定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。
目的:将算法的使用和算法的实现分离开来。
比如:

if(input == 'A'){
    return 1;
}
if(input == 'B'){
    return 2;
}
if(input == 'C'){
    return 3;
}
//或者
switch(input){
    case 'A':
        console.log(1);
        break;
    case 'B':
        console.log(2);
        break;
    case 'C':
        console.log(3);
        break;
}

对于这种有多个if-else和switch语句的情况,可以使用策略模式来处理。


策略模式有两部分组成:
一、策略类:封装了具体的算法,并负责具体计算过程。
二、环境类:接受客户的请求,然后将请求委托给某个策略类

//策略类Strategy
var strategies = {
    "A": function(num){
        return 1 + num;
    },
    "B": function(num){
        return 2 + num;
    },
    "C": function(num){
        return 3 + num;
    }
};
//环境类Context
var calculate = function(level,num){
    return strategies[level](num);
};
//调用
result = calculate('A',10);


使用策略模式也可以用来封装一系列的业务规则,只要这些业务规则指向的目标一致,并且可以被替换使用,我们就可以用策略模式来封装它们。

表单校验:
一般写法:

function checkForm(){
    if($("#name").val()==''){
        alert('用户名不能为空!');
        return false;
    }
    if($("#password").val().length<6){
        alert('密码长度不能少于6位!');
        return false;
    }
    if(!/(^1[3|5|8][0-9]{9}$)/.test($("#phone").val())){
        alert('手机号格式不正确!');
        return false;
    }
}

使用“策略模式”:

/***********************策略对象Strategy***********************/
var strategise={
    isEmpty: function(value,errorMsg){
        if(value === ''){
            return errorMsg;
        }
    },
    minLength: function (value,length,errorMsg) {
        if(value.length<length){
            return errorMsg;
        }
    },
    isMobile: function (value,errorMsg) {
        if(!/(^1[3|5|8][0-9]{9}$)/.test(value)){
            return errorMsg;
        }
    }
};

/***********************Validator类Context***********************/
var Validator= function () {
    this.cache=[]; //保存校验规则
};

Validator.prototype.add = function(dom,rules){
    var self = this;
    for(var i=0, rule; rule=rules.strategy.split(":")){
        (function(rule){
            var strateAry = rule.strategy.split(":");
            var errorMsg = rule.errorMsg;
            
            self.cache.push(function(){
                var strategy = strateAry.shift();//把数组的第一个元素从其中删除。
                strateAry.unshift(dom.val());    //向数组的开头添加input元素的值。
                strateAry.push(errorMsg);    //在数组尾部添加error信息
                return strategies[strategy].apply(dom,strateAry);
            });
        })(rule)
    }
};

Validator.prototype.start = function(){
    for(var i=0, Func; Func=this.cache[i];i++){
        var errorMsg = Func();
        if(errorMsg){
            return errorMsg;
        }
    }
};

/***********************调用***********************/
var checkForm = function(){
    var validator = new Validator();
    
    validator.add($("#name"),[{
        strategy: 'isEmpty',
        errorMsg: '用户名不能为空!'
    },{
        strategy: 'minLength:6',
        errorMsg: '用户名长度不能小于6位'
    }]);
    validator.add($("#password"),[{
        strategy: 'minLength:6',
        errorMsg: '密码长度不能小于6位'
    }]);
    validator.add($("#phone"),[{
        strategy: 'isMobile',
        errorMsg: '手机号格式不正确!'
    }]);
    
    var errorMsg = validator.start();
    return errorMsg;
}
$("form").submit(function(){
    var errorMsg = checkForm();
    if(errorMsg){
        alert(errorMsg);
        return fasle;
    }
});

优点:
1、采用组合、委托和多态等技术和思想,有效地避免多重条件选择语句。
2、对“开放封闭原则”完美支持,将算法独立封装在strategy,使得它们易于切换、理解和扩展。
3、策略模式中的算法也可以复用在系统的其他地方,从而避免重复的复制粘贴工作。
4、利用组合和委托让Context拥有执行算法的能力,这也是继承的一种轻便替代方案。

原文地址:https://www.cnblogs.com/boliang/p/4820015.html