设计模式前端应用——策略模式

一、基础知识

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设计模式与开发实践》(作者曾探)一书,做一些笔记来加深印象,有不正确的地方欢迎指正~

 

posted on 2018-09-18 18:33  天株  阅读(1647)  评论(0编辑  收藏  举报