策略模式

啥时策略模式?

举个例子,假如你从北京到杭州,可以选择坐飞机去,还可以坐汽车去,还可以自驾去。

每个方法都可以去。

策略模式就是实现一个任务有多个方法,这些方法都可以相互替换。把这些方法封装起来就是策略模式。

再举个例子,年终奖发放,绩效s的年终奖是工资的4倍。绩效A的年终奖是工资的3倍。绩效B的年终奖是工资的2倍。

js实现

var strategies={
    S: function (salary) {
       return salary * 4
    },
    A: function (salary) {
       return salary * 3
    },
    B: function (salary) {
       return salary * 2
    }
}

var caculateBouns = function (level,salary) {
  return strategies[level](salary)
}

console.log(caculateBouns('S',2000))
console.log(caculateBouns('A',3000))
console.log(caculateBouns('B',4000))

从定义上来看,策略模式就是用来封装算法的。

来点实用的。常见的表单验证如何用到策略模式呢?

假设我们正在编写一个用户注册的页面,在点击注册按钮之前,有以下几条校验规则。

1 :用户名不能为空

2 :密码长度不能少于6位

3: 手机号码必须符合格式

var registForm = document.getElementById('registForm');
registForm.onSubmit = function(){
   if(registForm.userName.value === ''){
      alert('用户名不能为空')
      return false
   }
   if(registForm.password.value.length < 6){
      alert('密码长度不能少于6位')
      return false
   }
   if(!/^1[3|5|8|7]\d{9}$/.test(registForm.phoneNumber.value)){
      alert('手机格式不正确')
      return false
   }
}

是不是你经常这么写?我也经常这么写。要想成为一名更优秀的程序员就要时刻反思自己的代码

那么这段代码有什么缺点呢??

1 registForm.onsubmit函数比较庞大,包含了很多if语句

2 函数缺乏弹性,如果新增一条校验规则,或者把密码长度从6改为8,我们就必须修改函数,这与开放-封闭原则相违背。

开放是对扩展开放,扩展功能是可以的。封闭是对修改封闭,对函数的内部修改是不提倡的,尽量不要去修改写过的代码。

3 算法的复用性差,如果项目中新增了另一个表单,这个表单也需要进行一些类似的校验。那我们就只能复制这段代码,这显然不是上策。

使用策略模式来优化以上代码

首先我们需要把这些校验规则封装成策略对象

// 策略类(包含哪些校验规则)
var strategies = {
    isNotEmpty: function(value,errorMsg){
       if(value === ''){
         return errorMsg
       }
    },
    minLength: function(value,length,errorMsg){
       if(value.length < length){
         return errorMsg
       }
    },
    isMobile: function(value,errorMsg){
       if(!/^1[3|8|9|5]\d{9}$/.test(value)){
         return errorMsg
       }
    }
}
// 校验容器
var Validator = function () {
  this.cache = []; // 缓存方法
}
validator.prototype.add=function(dom,rules){
  var self = this;
  for(let i =0,rule;rule = rules[i++]){
    let strategyAry = rule.strategy.split(':');
    let errorMsg = rule.errorMsg;
    self.cache.push(function(){
       var strategy = strategyAry.shift(); // 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
       startegyAry.unshift(dom.value) // 从头加 
       startegyAry.push(errorMsg) // 从尾部加 [value,length,errorMsg]
       return strategies[strategy].apply(dom,startegyAry) 
    })
  }
}
Validator.prototype.start = function (){
   for(let i = 0,validatorFun;validatorFun = this.cache[i++]){
      var errMsg = validatorFun()
      if(errMsg){
        return errMsg
      }
   }
}
// 客户端调用
var registForm = document.getElementById('registForm')
var validatorFun = function(){
   var validator = new Validator()
   validator.add(registForm.userName,[{
     startegy: 'isNotEmpty',
     errorMsg: '用户名不能为空'
   },{
     strategy: 'minLength: 10',
     errorMsg: '用户名长度不能小于10'
   }])
   validator.add(registForm.password,[{
     strategy: 'minLength:8',
     errorMsg: '密码不能少于6'
   }])
   validator.add(registForm.phoneNumber,[{
      strategy: 'isMobile',
      errorMsg: '手机格式不正确'
   }])
   var errorMsg = validator.start();
   return errorMsg
}


registForm.onSubmit= function(){
   var errMsg = validatorFun();
   if(errMsg){
     alert(errMsg)
     return false                              
   }
}

这样一来,校验规则只可以扩展,不需要再去修改已有的规则。还可以应用于所有的表单校验。

 

总结: 在程序中使用策略模式就需要策略类,写策略类就需要先知道所有的策略。这比把所有逻辑多起在一起使用if-else要好得多。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值