JS戰略形式《JavaScript設想形式與開闢實踐》瀏覽筆記

戰略形式的定義是:
定義一系列的算法,把它們一個個封裝起來,而且是它們能夠互相替代

  • 戰略形式能夠防止代碼中的多重推斷前提。
  • 戰略形式很好的表現了開放-關閉準繩,將一個個算法(解決方案)封裝在一個個戰略類中。便於切換,明白,擴大。
  • 戰略中的種種算法能夠反覆應用在體系的各個地方,防止複製粘貼。
  • 戰略形式在順序中或多或少的增添了戰略類。但比堆砌在營業邏輯中要清楚清楚明了。
  • 違背起碼學問準繩,必須要相識種種戰略類,才更好的在營業中運用。

此文僅紀錄本人瀏覽《JavaScript設想形式與開闢實踐》這個本時的覺得,謝謝作者曾探寫出這麼好的一本書。若有搪突,若有毛病,請聯絡本人處置懲罰。

簡樸的營業場景

盤算員工年終獎須要依據差別的員工績效盤算差別的獎金。比方,績效為S的人年終獎有4倍工資。績效A的人年終獎有3倍工資,績效B的人有2倍工資。

用代碼完成:

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

calculateBonus('S', 2000) // 8000
calculateBonus('A', 2000) // 6000

實在上面一段代碼已能敷衍現在的場景。然則,當獎金的評定須要增添一個績效C,或許轉變績效A的盤算體式格局。此時須要變動上面這個calculateBonus要領的內部結構,云云下去,這個要領內部將變得蕪雜。

設想形式中很主要的一點就是將穩定和變分離出來。這裏變的是怎樣算。穩定的是依據一個績效取得一個效果。所以上述代碼重寫,把種種算法封裝在一個個戰略類中(傳統面向對象的模擬):

var performanceS = function() {}
performanceS.prototype.calc = function(salary) {
    return salary * 4
}

var performanceA = function() {}
performanceA.prototype.calc = function(salary) {
    return salary * 3
}

var performanceB = function() {}
performanceB.prototype.calc = 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(strategy) {
    this.strategy = strategy //設置員工績效對應的戰略對象
}

Bonus.prototype.getBonus = function() { //獵取獎金數額
    return this.strategy.calc(this.salary) //把盤算獎金的操縱託付個對應的戰略對象
}

var bonus = new Bonus()
bonus.setSalary(10000)
bonus.setStrategy(new performanceA())

console.log(bonus.getBonus()) // 30000

JavaScript版本的戰略形式

在JavaScript中能夠將一個個戰略類寫成函數,然後封裝在對象中:

// 盤算獎金的例子
var strategies = {
    S: function(salary) {
        return salary * 4
    },
    A: function(salary) {
        return salary * 3
    },
    B: function(salary) {
        return salary * 2
    }
}

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

console.log(calculateBonus('S', 10000)) // 40000
console.log(calculateBonus('S', 20000)) // 80000

更廣義的“算法”

戰略形式指的是一系列的算法(戰略),而且把它們封裝起來。盤算獎金的列子中就封裝了一些算法。實在世紀營業中也能夠應用戰略形式來封裝一些“營業劃定規矩”。

表單考證

在Web項目中每每有許多場景須要提交表單。前端在把數據提交到後端之前,須要舉行一波表單考證,來削減不必要的收集要求。在表單考證中每每會有多種校驗劃定規矩,頁面中能夠會有多個表單要舉行考證。此時能夠用戰略形式來完成一個表單考證:

<form action="" mothod="post" id="registerForm">
  輸入用戶名: <input type="text" name="userName">
  輸入暗碼: <input type="text" name="password">
  輸入手機號碼:<input type="text" name="phoneNumber">
  <button>提交</button>
</form>
<script>
    var strategies = {
      isNonEmpty: 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|5|8][0-9]{9}$)/.test(value)){
          return errorMsg
        }
      }
    }

    // 定義Validator類
    var Validator = function(){
      this.cache = []
    }

    Validator.prototype.add = function(dom, rule, errorMsg){
      var ary = rule.split(':')
      this.cache.push(function(){
        var strategy = ary.shift()
        ary.unshift(dom.value)
        ary.push(errorMsg)
        return strategies[ strategy ].apply(dom, ary)
      })
    }

    Validator.prototype.start = function(){
      for (var i = 0,validatorFunc;validatorFunc = this.cache[i++];){
        var msg = validatorFunc()
        if(msg){
          return msg
        }
      }
    }

    var validataFunc = function() {
      var validator = new Validator()
    // 增加校驗劃定規矩
      validator.add(registerForm.userName,'isNonEmpty', '用戶名不能為空')
      validator.add(registerForm.password,'minLength:6', '暗碼長度不能少於6位')
      validator.add(registerForm.phoneNumber,'isMobile', '手機花樣不正確')

      var errorMsg = validator.start()
      return errorMsg
    }

    var registerForm = document.getElementById('registerForm')
    registerForm.onsubmit = function(){
      var errorMsg = validataFunc()
      if (errorMsg) {
        console.log(errorMsg)
        return false
      }
    }
</script>

總結

  • 在一樣平常開闢中一些東西函數能夠封裝在一起,構成本身的東西庫。削減不必要的代碼複製粘貼。
  • 覺得敲代碼頭腦更主要啦,這裏戰略形式表現了開放-關閉準繩下降代碼的耦合度。這些理念都是我本身在敲代碼的路上要逐步進修和積聚的。
  • 敲出來的代碼不能只要本身熟悉。要多注重細節,時候去想哪些代碼能夠再多完美。
  • 固然不是一切的東西都要分來分去,一個簡樸的需求為了設想形式而去設想形式也是不可取的。

love & peace

參考

《JavaScript設想形式與開闢實踐》—— 曾探

    原文作者:羅高
    原文地址: https://segmentfault.com/a/1190000015252321
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞