首页 > 代码库 > 策略者模式
策略者模式
1. 策略模式定义和优点
策略者模式: 定义一系列的算法 把它们一个个封装起来 并使他们可以相互替换。优点:
A) 策略模式利用组合 委托等思想 有效避免很多if条件语句。
B) 策略模式提供了开发——封闭原则 使代码更容易理解和扩展。
C) 策略模式中的代码可以复用。
2. 策略模式的使用
使用策略模式计算奖金
公司的年终奖是根据员工的工资和绩效来考核的,绩效为A的人,年终奖为工资的4倍,绩效为B的人,年终奖为工资的3倍,绩效为C的人,年终奖为工资的2倍;现在我们使用一般的编码方式会如下这样编写代码:
缺点如下:
A) calculateBouns 函数包含了很多if else
B) calcualteBouns 函数缺乏弹性 假如还有D等级 那么我们还需要在calculateBouns函数中添加盘算等级D的if语句
C) 算法复用性差 如果在其他地方也有类似这样的算法 但是规则不一样 这么我们的代码不能通用。
策略模式
3. 表单验证
我们经常要进行表单验证 比如注册登录对话框 我们登录之前要进行验证操作比如:
A) 用户名不能为空
B) 密码长度不能小于6
C) 手机号码必须符合格式
我之前的写法
但是这样编写代码有如下缺点:
- registerForm.onsubmit 函数比较大,代码中包含了很多if语句;
- registerForm.onsubmit 函数缺乏弹性,如果增加了一种新的效验规则,或者想把密码的长度效验从6改成8,我们必须改registerForm.onsubmit 函数内部的代码。违反了开放-封闭原则。
- 算法的复用性差,如果在程序中增加了另外一个表单,这个表单也需要进行一些类似的效验,那么我们可能又需要复制代码了;
策略模式来重构表单校验。
第一步封装策略对象
第二步: 准备实现Validator类,Validator类在这里作为Context,负责接收用户的请求并委托给strategy 对象
Validator类在这里作为Context,负责接收用户的请求并委托给strategys对象。上面的代码中,我们先创建一个Validator对象,然后通过validator.add方法往validator对象中添加一些效验规则,validator.add方法接收3个参数,如下代码:
validator.add(registerForm.password,’minLength:6′,’密码长度不能小于6位’);
registerForm.password 为效验的input输入框dom节点;
minLength:6: 是以一个冒号隔开的字符串,冒号前面的minLength代表客户挑选的strategys对象,冒号后面的数字6表示在效验过程中所必须验证的参数,minLength:6的意思是效验 registerForm.password 这个文本输入框的value最小长度为6位;如果字符串中不包含冒号,说明效验过程中不需要额外的效验信息;
第三个参数是当效验未通过时返回的错误信息;
当我们往validator对象里添加完一系列的效验规则之后,会调用validator.start()方法来启动效验。如果validator.start()返回了一个errorMsg字符串作为返回值,说明该次效验没有通过,此时需要registerForm.onsubmit方法返回false来阻止表单提交.
如果我们既要效验输入框是否为空,还要效验输入框的长度不要小于10位的话,那么我们期望需要像如下传递参数:
最后上一张全部代码
1 // 策略对象 2 var strategys = { 3 isNotEmpty: function(value,errorMsg) { 4 if(value =http://www.mamicode.com/== ‘‘) { 5 return errorMsg; 6 } 7 }, 8 // 限制最小长度 9 minLength: function(value,length,errorMsg) {10 if(value.length < length) {11 return errorMsg;12 }13 },14 // 手机号码格式15 mobileFormat: function(value,errorMsg) {16 if(!/(^1[3|5|8][0-9]{9}$)/.test(value)) {17 return errorMsg;18 }19 } 20 };21 var Validator = function(){22 this.cache = []; // 保存效验规则23 };24 Validator.prototype.add = function(dom,rules) {25 var self = this;26 for(var i = 0, rule; rule = rules[i++]; ){27 (function(rule){28 var strategyAry = rule.strategy.split(":");29 var errorMsg = rule.errorMsg;30 self.cache.push(function(){31 var strategy = strategyAry.shift();32 strategyAry.unshift(dom.value);33 strategyAry.push(errorMsg);34 return strategys[strategy].apply(dom,strategyAry);35 });36 })(rule);37 }38 };39 Validator.prototype.start = function(){40 for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {41 var msg = validatorFunc(); // 开始效验 并取得效验后的返回信息42 if(msg) {43 return msg;44 }45 }46 };47 // 代码调用48 var registerForm = document.getElementById("registerForm");49 var validateFunc = function(){50 var validator = new Validator(); // 创建一个Validator对象51 /* 添加一些效验规则 */52 validator.add(registerForm.userName,[53 {strategy: ‘isNotEmpty‘,errorMsg:‘用户名不能为空‘},54 {strategy: ‘minLength:6‘,errorMsg:‘用户名长度不能小于6位‘}55 ]);56 validator.add(registerForm.password,[57 {strategy: ‘minLength:6‘,errorMsg:‘密码长度不能小于6位‘},58 ]);59 validator.add(registerForm.phoneNumber,[60 {strategy: ‘mobileFormat‘,errorMsg:‘手机号格式不正确‘},61 ]);62 var errorMsg = validator.start(); // 获得效验结果63 return errorMsg; // 返回效验结果64 };65 // 点击确定提交66 registerForm.onsubmit = function(){67 var errorMsg = validateFunc();68 if(errorMsg){69 alert(errorMsg);70 return false;71 }72 }
策略者模式