设计模式之策略模式

来源:互联网 发布:java aes 解密算法 编辑:程序博客网 时间:2024/05/19 19:44

策略模式的定义:定义一系列的算法,把他们一个个封装起来,并且使它们可以互相替换


目录

1.面向过程的最初代码

2.使用组合模式

3.使用传统策略模式重构代码

4.javascript版本的策略模式

5.表单校验

6.使用策略后的代码

7.给某个输入框添加多个校验规则   

8.最终效果 http://runjs.cn/code/d4okpeeh

1.面向过程的最初代码:

<script>    var calculateBonus=function(performancelevel,salary){        if(performancelevel==="s"){            return salary*4;        }        if(performancelevel==="a"){            return salary*3;        }        if(performancelevel==="b"){            return salary*2;        }    };    calculateBonus("b",2000);    calculateBonus("s",6000);</script>

缺点:

1.包含多个if-else,这些语句会影响其他逻辑分支

2.缺乏弹性操作,如果需要添加或替换策略需要修改函数内部,违反“开放-封闭”原则


2.使用组合模式:

<script>    var s=function (salary){        return salary*4;    };    var a=function (salary){        return salary*3;    };    var b=function (salary){        return salary*2;    };    var calculateBonus=function(performancelevel,salary){        if(performancelevel==="s"){            return s(salary);        }        if(performancelevel==="a"){            return a(salary);        }        if(performancelevel==="b"){            return b(salary);        }    };    calculateBonus("s",300000);</script>
在最初代码基础上进行了改善,单还未解决最初代码的缺陷


3.使用传统策略模式重构代码:

<script>    //定义多个策略类------------    var performanceS=function(){};    performanceS.prototype.calculate=function(salary){        return salary*4;    };    var performanceB=function(){};    performanceB.prototype.calculate=function(salary){        return salary*2;    };    var performanceA=function(){};    performanceA.prototype.calculate=function(salary){        return salary*3;    };    //定义奖金类-------------------    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(1000);    bonus.setStrategy(new performanceA());//设置策略对象    console.log(bonus.getBonus());</script>

策略模式:

至少包含两部分---

1.策略类  --封装了具体的算法,并负责计算过程,可以划分为两部分【规则和使用规则】

 2.环境类----接受客户的请求,并随后委托给一个策略类


4.javascript版本的策略模式:

<script>    /*    * 在javascript中函数也是对象,所以javascript中的直接把strategy定义为一个策略集合对象*/    //策略对象    var strategies={        "s":function(salary){            return salary*4;        },        "a":function(salary){            return salary*3;        },        "b":function(salary){            return salary*2;        }    };    //代替传统策略模式里面的Bonus类,和命令模式的安装命令工具一样功能    var calculateBonus=function(level,salary){        return strategies[level](salary);    };    console.log(calculateBonus("s",20000));//80000    console.log(calculateBonus("a",10000));//30000</script>

在javascript中,函数也是对象,所以简单直接的吧strategy直接定义为一个包含策略集合的函数,context也没必要用bonus类来表示,这样代码更加简洁


5.表单校验

常见代码:

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title></title></head><body><form action="http://www.baidu.com" id="registerForm">    <div>        请输入用户名:<input type="text" name="userName"/>    </div>    <div>        请输入密码:<input type="text" name="password"/>    </div>    <div>        请输入手机号:<input type="text" name="phoneNumber"/>    </div>    <div>        <button>提交</button>    </div></form><script>    var registerForm=document.getElementById("registerForm");    registerForm.onsubmit=function(){        if(registerForm.userName.value==""){            alert("用户名不能为空");            return false;        }        if(registerForm.password.value.length<6){            alert("密码不能少于6位");            return false;        }        if(!/^[1][358][0-9]{9}$/.test(registerForm.phoneNumber.value)){            alert("手机号码不正确");            return false;        }    }</script></body></html>

6.使用策略后的代码:

<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title></title></head><body><form  id="registerForm">    <div>        请输入用户名:<input type="text" name="userName"/>    </div>    <div>        请输入密码:<input type="text" name="password"/>    </div>    <div>        请输入手机号:<input type="text" name="phoneNumber"/>    </div>    <div>        <button>提交</button>    </div></form><script>    var registerForm=document.getElementById("registerForm");    //定义策略类    var strategies={        isNonEmpty:function(value,errorMsg){            if(value===""){                console.log(this);//这里的this指向dom                return errorMsg;            }        },        minLength:function(value,length,errorMsg){            if(value.length<length){                return errorMsg;            }        },        isMobile:function(value,errorMsg){            if(!/^[1][358][0-9]{9}$/.test(registerForm.phoneNumber.value)){                return errorMsg;            }        }    };//定义Validator类----------------------    var Validator=function(){        this.cache=[];//保存校验规则    };    Validator.prototype.add=function(dom,rule,errorMsg){        var ary=rule.split(":");        this.cache.push(function(){            var strategy=ary.shift();//规则名            ary.unshift(dom.value);//dom的value            ary.push(errorMsg);//错误提示            console.log(ary);            //最终ary格式为["input的value","提示"]            return strategies[strategy].apply(dom,ary);//把策略模式在dom环境内运行        })    };    Validator.prototype.start=function(){        for(var i= 0,validatorFunc;validatorFunc=this.cache[i++];){            var msg=validatorFunc();//开始验证后返回信息            if(msg){                return msg;            }        }    };    //用户提交表单验证请求-------------var validataFunc=function(){    var validator=new Validator();//创建一个对象    validator.add(registerForm.userName,"isNonEmpty","用户名不能为空");    validator.add(registerForm.password,"minLength:6","密码长度不能少于6");    validator.add(registerForm.phoneNumber,"isMobile","手机号格式不对");    var errorMsg=validator.start();//获取校验结果    return errorMsg;};    registerForm.onsubmit=function(){        var errorMsg=validataFunc();//如果放回true说明为未通过校验        if(errorMsg){            alert(errorMsg);            return false;        }    }</script></body></html>


7.给某个输入框添加多个校验规则:

例如我们想校验它即不能为空同时限制长度为10,我们期待以这种格式进行校验:

validator.add(registerForm.userName,[{    strategy:"isNonEmpty",    errorMsg:"用户名不能为空"},{    strategy:"minLength:6",    errorMsg:"用户名不能长度不能小于6"}]);

我们只需要给原来的add方法里面添加个for就能实现了具体javascript代码如下:

<script>    /***********************策略************************/    //定义策略类    var strategies={        isNonEmpty:function(value,errorMsg){            if(value===""){                return errorMsg;            }        },        minLength:function(value,length,errorMsg){            if(value.length<length){                return errorMsg;            }        },        isMobile:function(value,errorMsg){            if(!/^[1][358][0-9]{9}$/.test(registerForm.phoneNumber.value)){                return errorMsg;            }        }    };    /***********************validator类************************/    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 ary=rule.strategy.split(":");                console.log(ary);//如果格式为"minLength:6"这样的将会给策略传入多一个参数6                var errorMsg=rule.errorMsg;                self.cache.push(function(){                    var strategy=ary.shift();//规则名                    ary.unshift(dom.value);//dom的value                    ary.push(errorMsg);//错误提示                    console.log(ary);                    //最终ary格式为["input的value","提示"]                    return strategies[strategy].apply(dom,ary);//把策略模式在dom环境内运行                })            })(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 validataFunc=function(){        var validator=new Validator();        validator.add(registerForm.userName,[{            strategy:"isNonEmpty",            errorMsg:"用户名不能为空"        },{            strategy:"minLength:6",            errorMsg:"用户名不能长度不能小于6"        }]);        validator.add(registerForm.password,[{            strategy:"minLength:6",            errorMsg:"密码长度不能小于6"        }]);        validator.add(registerForm.phoneNumber,[{            strategy:"isMobile",            errorMsg:"密码长度不能小于6"        }]);        var errorMsg=validator.start();        return errorMsg;    };    registerForm.onsubmit=function(){        var errorMsg=validataFunc();        if(errorMsg){            alert(errorMsg);                return false;            }    }</script>

8.最终效果:http://runjs.cn/code/d4okpeeh

0 0