策略者模式
Posted Befacebook
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了策略者模式相关的知识,希望对你有一定的参考价值。
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 === \'\') { 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 }
以上是关于策略者模式的主要内容,如果未能解决你的问题,请参考以下文章