设计模式前端应用——策略模式
一、基础知识
1、定义:定义一系列算法,把它们一个个封装起来,并且它们可以相互替换
2、实际应用:减少if else的使用,在每种情况执行不同代码的情况下,我们通常使用if else语句来进行操作,使得当前函数代码量庞大,修改麻烦,不灵活。
二、举例
1、旅行采用的不同的交通工具,飞机,高铁,动车,汽车,火车等等
2、根据绩效发放年终奖金。绩效分A B C等级,根据不同的等级发放多或少的奖金
3、form表单验证。对每一个输入框进行验证,可以验证是否为空,最小长度,是否符合电话号码,等等
三、策略模式的实现(以发放奖金和form表单验证为例)
1、发放奖金规则:绩效得A的员工,将拿到原本工资*3倍的钱;绩效得B的员工,将拿到原本工资*2倍的钱;绩效得C的员工,将拿到原本工资*1.5倍的钱。
(1)我们通常可能会这样写:
1 <script type="text/javascript"> 2 function calcSalary(original, grade) { //original:原本的工资 grade:绩效等级 3 var final; 4 if(grade == "A") { 5 final = original*3 6 }else if(grade == "B") { 7 final = original*2 8 }else if(grade == "C") { 9 final = original*1.5 10 } 11 return final 12 } 13 console.log(calcSalary(2000,'A')) // 6000 14 console.log(calcSalary(2000,'B')) //4000 15 console.log(calcSalary(2000,'C')) //3000 16 </script>
(2)使用策略模式重构代码
再回顾一遍策略模式的定义:定义一系列算法,把它们一个个封装起来,并且它们可以相互替换
我们可以观察在计算绩效奖金的过程中,算法的使用方式是不变的,都是根据某个算法取得计算后的奖金数额。而算法的实现是各异和变化的,每种绩效对应着不同的计算规则。一个基于策略模式的程序至少由两部分组成,一组策略和一个调用环境。接下来看一下具体实现:
1 <script type="text/javascript"> 2 var strategies = { //一组策略 3 "A": function(original) { 4 return original*3 5 }, 6 "B": function(original) { 7 return original*2 8 }, 9 "C": function(original) { 10 return original*1.5 11 } 12 } 13 function calcSalary(original, grade) { //调用环境 14 return strategies[grade](original) 15 } 16 console.log(calcSalary(2000,'A')) // 6000 17 console.log(calcSalary(2000,'B')) // 4000 18 console.log(calcSalary(2000,'C')) // 3000
2、form表单验证:一个注册表单,有用户名和密码,其中用户名不能为空,密码长度要大于6位,当提交表单的时候对表单做验证。
(1)我们通常可能会这样写:
1 <form id="registerForm" class="form"> 2 <div class="form-item"> 3 <input type="text" name="username"> 4 </div> 5 <div class="form-item"> 6 <input type="text" name="password"> 7 </div> 8 <button type="submit">注册</button> 9 </form> 10 <script type="text/javascript"> 11 var registerForm = document.getElementById('registerForm'); 12 registerForm.onsubmit = function() { 13 console.log('submit') 14 if(registerForm.username.value == '') { 15 alert('用户名不能为空'); 16 return false; 17 }else if(registerForm.password.value.length >= 6) { 21 alert('密码不得小于6位') 22 return false; 23 } 24 } 25 </script>
(2)使用策略模式重构代码
看了之前计算薪水的例子,可知第一步我们要把所有的策略封装起来:
1 var strategies = { 2 isNotEmpty: function(value, msg) { 3 if(value === '') { 4 return msg 5 } 6 }, 7 minLength: function(value, length, msg) { 8 if(value.length < length) { 9 return msg 10 } 11 } 12 }
第二步是创建调用策略的环境:因为需要判断使用哪种策略,以及使用这种策略是否需要传参数值(例:minLength策略需要传数值),所以我们对解析和判断的过程做一下封装
1 var Validator = function(){ 2 this.cache = [] 3 }; 4 Validator.prototype.add = function(dom, rule, msg) { 5 var ruleKey = []; 6 var ruleVal = '' 7 if(rule.indexOf(':')!=-1) { 8 ruleKey = rule.split(':')[0]; 9 ruleVal = rule.split(':')[1]; 10 } else { 11 ruleKey = rule; 12 } 13 this.cache.push(function(){ 14 var temp=[] 15 temp.push(dom.value) 16 if(ruleVal) { 17 temp.push(ruleVal) 18 } 19 temp.push(msg) 20 return strategies[ruleKey].apply(dom, temp); 21 }) 22 } 23 Validator.prototype.validate = function() { 24 var count = 0 25 this.cache.forEach(function(item){ 26 var msg = item() 27 if(msg) { 28 count++ 29 alert(msg) 30 } 31 }) 32 if(count > 0) { 33 return false 34 } else { 35 return true 36 } 37 };
最后创建一个Validator实例,在表单提交事件中调用validate方法:
var test = new Validator() test.add(registerForm.username, 'isNotEmpty', '用户名不能为空'); test.add(registerForm.password, 'minLength: 6','密码至少6位'); registerForm.onsubmit = function() { if(!test.validate()) { return false; } }
总结:最近在看《JavaScript设计模式与开发实践》(作者曾探)一书,做一些笔记来加深印象,有不正确的地方欢迎指正~