读书笔记之战略形式

近来在看《javascript设想形式与开辟实践》。

var calc = function(level,salary){
         if(level === "A"){
            return 3*salary
         }
         if(level === "B"){
            return 2*salary
         }
         if(level === "C"){
            return 1*salary
         }
}

这段代码看起来非常简朴,然则跟着后期的拓展,要增添更多的if语句,calc函数会变得越发巨大,不易于保护。
假如我要修正原有的盘算分之,能够每次都要修正calc这个要领。实际上,这个calc这个要领的设想初志只是为了返回 绩效工资。
在全部代码的别的部份,能够还须要这个盘算要领,岂非还要copy一份过去么,那末一样的修正要修正两块代码。

用战略形式来重构代码

  • 战略形式指的是定义一系列的算法,把他们一个个都封装起来。将稳定的部份和变化的部份支解最先每一个设想形式的主题,战略形式的目标就是将算法的运用与算法的完成星散开来。

  • 再说上边的需求,我们简朴思索下,实在变化的部份就是员工的品级和工资,而我们的目标就是返回绩效工资这部份是稳定的

//  依据员工的level和salary 金额的盘算
var straigies = {
    “A”: function(salary){
        return fn*3
    },
    “B”: function(salary){
        return fn*2
    },
    “C”: function(salary){
        return fn*1
    }
}
//稳定的部份
var calc = function(level,salary){
     return straigies[level](salary)
}
// 实行
calc("A",5000)    // => 15000

比较下两段代码,不见了不友好的 if推断,算法(战略)都放在了straigies 中,后续需求 只须要保护straigies对象即可。

  • 用战略形式来重构表单考证

许多须要提交表单的营业场景,都须要以下构造的代码

$('submitBtn').on('click',functioin(){
    if($name.value().length < 6){
         console.log("用户名长度不能少于6")
    }
   if($phone.value() != ''){
        console.log("电话号码不能为空")
 }
  ajaxFn()
})

跟着 推断前提的增添,函数的构造会愈来愈痴肥巨大,而须要修正推断的前提,就又要深切指定的if推断去挑选,纯真的新增划定规矩在这个函数里,复用性太差。连系战略形式,能够把if推断这一部份 函数里提取出来从新封装,进步代码的复用性和可读性。

对代码构造的希冀

$('submitBtn').on('click',functioin(){
  var form = document.querySelector('.form');
  var validator = new validator ();
  validator.addrules(form.username,"isNonEmpty","不能为空")
  validator.addrules(form.phone,"minLength:6","起码为6位")
  var erroMsg = validator.start();
  if(erroMsg){
     alert(validator);
     return false
  }
  ajaxFn()
})

我们先封装战略类

var stratigies = {
    isNonEmpty: function(value,erromsg){
          if(value == ""){
          return erromsg
        }
    },
  minlength: function(value,length,erromsg){
       if(value.length < length){
          return erromsg
      }
 }
}

封装 考证(validator类)

var Validator = function(){
  this.cache = [] //用来缓存
}
Validator.prototype.add = function(item,rule,erroMsg){
  var arg = rule.split(":") // rule= >  "isEmpty" => ["isEmpty"] ||  "minLength:5"=> ["minlength", “5”];
  this.cache.push(function(){
      var strategy = arg.shift();  // =>"isEmpty" || minLength
      arg.unshift(item.value);  //[value] || [value,5]
      arg.push(errMsg)// [value,errMsg] || [value,5,errMsg]
      return  stratigies[strategy].apply(item,arg)
  })
}
//start要领就是遍历这个Validator里缓存的要领并实行
Validator.prototype.start = function(){
  for(var i=0;i<this.cache.length;i++){
      var fn = this.cache[i];
      var msg = fn()    // =>最先校验,
      if(msg){
         return msg   // 假如msg有值 就申明考证不通过,跳出轮回
      }
  }
}

此时,假如须要增添划定规矩 或是修正考证划定规矩,就很简朴了
我们能够在stratigies里增添战略,也能够在 提交表单的函数里,新增或许修正划定规矩

validator.addrules(form.phone,"minLength:6") =》 validator.addrules(form.phone,"minLength:10")

很蛋疼的是,对用户名推断只能一次输入一种划定规矩,假如须要加一种推断划定规矩,我就要在add一次strategy,
书中供应了进一步的拓展。

//预期
  validator.addrules(form.username,[
   {
      "erroMsg": "不能为空",
      "strategy": 'isNonEmpty'
    },
   {
      "erroMsg": "最小为6位",
      "strategy": 'minLength:6'
    }
])

将战略用数组的体式格局传入validator对象里,缓存在this.cache里,只须要调解对应的add要领就能够

//old type
Validator.prototype.add = function(item,rule,erroMsg){
  var arg = rule.split(":") // rule= >  "isEmpty" => ["isEmpty"] ||  "minLength:5"=> ["minlength", “5”];
  this.cache.push(function(){
      var strategy = arg.shift();  // =>"isEmpty" || minLength
      arg.unshift(item.value);  //[value] || [value,5]
      arg.push(errMsg)// [value,errMsg] || [value,5,errMsg]
      return  stratigies[strategy].apply(item,arg)
  })
}
// new Type
Validator.prototype.add = function(item,rules){
   var  _this = this; //保留this指针   for轮回里的的自实行函数的this指向window,用_this修复指针
  //遍历rules
 for(var i = 0;i<rules.length;i++){
    var rule = rules[i];
    (function(rule ){
       var arg = rule.strategy.split(":") // rule= >  "isEmpty" => ["isEmpty"] ||  "minLength:5"=> ["minlength", “5”];
       var  errMsg = rule.errMsg;
      _this.cache.push(function(){
            var strategy = arg.shift();  // =>"isEmpty" || minLength
            arg.unshift(item.value);  //[value] || [value,5]
            arg.push(errMsg)// [value,errMsg] || [value,5,errMsg]
            return  stratigies[strategy].apply(item,arg)
         })
      })(rule)
  }
}
    原文作者:最普通的一个
    原文地址: https://segmentfault.com/a/1190000007286881
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞