js策略模式 实现表单验证

策略模式

定义:定义一系列的算法,把它们一个一个封装起来,并且使它们可以相互替换。

使用策略模式计算奖金

需求为绩效S的人4倍奖金,绩效为A的人3倍奖金,绩效为B的人年终奖是2倍工资。

  var caculateBonus = function(performanceLevel, salary){
      if(performanceLevel === 'S'){
          return salary * 4;
      }
      if(performanceLevel === 'A'){
          return salary * 3;
      }
      if(performanceLevel === 'B'){
          return salary * 2;
      }
  }

这段代码有一些缺点,如果我们想改变绩效的奖金系数,我们必须修改calculateBonus函数的内部实现,这是违反开放-封闭原则的。算法的复用性很差,如果在程序的其他地方需要重用这些计算奖金的方法,就只有复制和粘贴。

使用组合函数重构代码

我们把各种算法封装到一个个小函数里面,这些小函数有着良好的命名,可以一目了然知道它对应者哪种算法

   var performanceS = function(salary){
       return salary * 4;
   };
   var performanceA = function(salary){
       return salary * 3;
   };
   var performanceB = function(salary){
       return salary * 2;
   }
   var calculateBonus = function(performanceLevel, salary){
      if(performanceLevel === 'S'){
         return performanceS(salary);
      }
      //...
   }

这样依然没有解决我们的问题\

使用策略模式重构代码

一个基于策略模式的程序至少有两部分组成,第一个部分是策略类,策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类Context,Context接受客户的请求,随后把请求委托给一个策略类。要做到这点,说明Context中要维持某个策略对象的引用

   var performanceS = function(){};
   performanceS.prototype.calculate = function(salary){
       return salary * 4;
   };
   var performanceA = function(){};
   performanceA.prototype.calculate = function(salary){
       return salary * 3;
   };
   var performanceB = function(){};
   performanceB.prototype.calculate = function(salary){
       return salary * 2;
   };

接下来定义奖金类Bonus

   var Bonus = function(){
       this.salary = null;  
       this.strategy = null; //绩效等级对应的策略对象
   }
   Bonus.prototype.setSalary = function(salary){
       this.salary = salary;
   }
   Bonus.prototype.setStrategy = function(salary){
       this.strategy = strategy;
   }
   Bonus.prototype.getBonus = function(){
       return this.strategy.calculate(this.salary);
   }

接下来

   var bonus = new Bonus();
   bonus.setSalary(10000);
   bonus.setStrategy(new performanceS());//设置策略对象
   console.log(bonus.getBonus());
   bonus.setStrategy();
js版本的策略模式

我们让strategy对象从各个策略类中创建而来,这时模拟一些传统的面向对象语言的实现,实际上在js中,函数也是对象,所以更简单的做法是把strategy直接定义成函数

   //[ˈstrætədʒi]策略
   var strategies = function(){
       'S': function(salary){
           return salary * 4;
       },
       'A': function(salary){
           return salary * 3;
       },
       'B': function(salary){
           return salary * 2;
       }
   };

同样,Context也没有必要必须用Bonus类表示,我们依然用calculateBonus函数充当Context来接受用户的请求

   var calculateBonus = function(level, salary){
       return strategies[level](salary);
   }
   console.log(calculateBonus('S', 20000));
   console.log(calculateBonus('A', 10000));
表单校验

我们首先要将表单的校验逻辑都封装成策略对象

   var strategies = {
       isNonEmpty: function(value, errorMsg){
          if(value === ''){
              return errorMsg;
          }
       },
       minLength: function(value, length, errorMsg){
          if(value.length < length){
              return errorMsg;
          }
       },
       isMobile: function(value){
           if(!/(^1[3|5|8][0-9]{9}$)/.test(value)){
               return errorMsg;
           }
       }
   }

然后实现一个validataFunc类

   var Validator = function(){
       //保存校验规则
       this.cache = [];
   };
   Validator.prototype.add = function(dom, rule, errorMsg){
       //把strategy和参数分开
       var arr = rule.split(':');
       this.cache.push(function(){
          //statefy: minLength
          var strategy = arr.shift();
          //[dom.value, 10]
          arr.unshift(dom.value);
          //[dom.value, 10, errorMsg]
          arr.push(errorMsg);
          //return minLength.apply(dom, [dom.value, 10, errorMsg])
          return strategies[strategy].apply(dom, arr);
       })
   };
   Validator.prototype.start = function(){
      for(var i = 0; i <  this.cache.length; i++;){
         var msg =  this.cache[i];
         //如果有确切的返回值,说明校验没有通过
         if(msg){
             return msg;
         }
      }
   }

这样重构之后,我们在修改某个校验规则的时候,只需要编写或者改写少量的代码

   validator.add(registerForm.userName, 'minLength: 10', '用户名长度不能小于10位');

策略模式也有一些缺点,使用策略模式会在程序中增加许多策略对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值