设计模式之策略模式
来源:互联网 发布: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
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- 设计模式之策略模式
- Linux ar --创建静态库.a文件
- AndroidStudio常用快捷键(持续更新,用一个记一个)
- 关于Ceph现状与未来的一些思考
- EditText默认不获得焦点
- 字节与字符_字节流与字符流_ASCII与Unicode_GB2312_GBK_GB18030_BIG-5
- 设计模式之策略模式
- 获取当前应用程序的版本号
- java.lang.NoClassDefFoundError异常
- Python基础教程(第2版•修订版)代码清单2-3 勘误
- Linux arp --操作ARP缓存
- Linux awk --对文本和数据进行处理
- 串口输出和按键消抖
- 使用弱引用指向内部变量时的注意事项.jpg
- poj1185 炮兵阵地