策略者模式

 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) 手机号码必须符合格式

  

  我之前的写法

    

  但是这样编写代码有如下缺点:

  1. registerForm.onsubmit 函数比较大,代码中包含了很多if语句;
  2. registerForm.onsubmit 函数缺乏弹性,如果增加了一种新的效验规则,或者想把密码的长度效验从6改成8,我们必须改registerForm.onsubmit 函数内部的代码。违反了开放-封闭原则
  3. 算法的复用性差,如果在程序中增加了另外一个表单,这个表单也需要进行一些类似的效验,那么我们可能又需要复制代码了;

    策略模式来重构表单校验。

  第一步封装策略对象

    

  第二步: 准备实现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 }
posted on 2016-10-09 11:40  Befacebook  阅读(708)  评论(0编辑  收藏  举报