js 設計模式——策略模式


策略模式(Strategy)

定義:將定義的一組算法封裝起來,使其相互之間可以替換。封裝的算法具有一定的獨立性,不會隨客戶端的變化而變化

廢話不多說,先來個例子

// 例如要寫一個計算兩個數加減乘除的方法,會有人這么寫
countNum(type, num1, num2) {
  if(type === 'add'){
    return num1 + num2
  } else if(type === 'subtract'){
    return num1 - num2
  } else if(type === 'multiply'){
    return num1 * num2
  } else {
    return num1 / num2
  }
}

countNum('add', 9, 3)       // 12
countNum('subtract', 9, 3)  // 6
countNum('multiply', 9, 3)  // 27
countNum('', 9, 3)          // 3

上面的例子,一定會有人這么寫的,你要說沒有我也沒辦法(~ ̄▽ ̄)~,這樣寫首先不利於維護,其實也不好方便擴展

改進一下:

let countNum = {
  add(num1, num2) {
    return num1 + num2
  },
  subtract(num1, num2) {
    return num1 - num2
  },
  multiply(num1, num2) {
    return num1 * num2
  },
  divide(num1, num2) {
    return num1 / num2
  },
}

countNum.add(9, 3)      // 12
countNum.subtract(9, 3) // 6
countNum.multiply(9, 3) // 27
countNum.divide(9, 3)   // 3

上面的例子就可以看成是一個策略模式

now,現在有個需求,快要聖誕節,所以咧,超市中一部分商品8折出售,一部分9折出售,等到元旦還要搞大事,普通用戶滿100返30,VIP用戶滿100返50,用策略模式來實現

// 定義一個策略對象
let priceceStrategy = function(){
  // 內部算法對象 
  let strategy = {
    return30(price){
      return price + parseInt(price / 100) * 30
    },
    return50(price){
      return price + parseInt(price / 100) * 50
    },
    price80(price){
      return price  * 80 / 100
    },
    price90(price){
      return price  * 90 / 100
    }
  }
  // 策略方法調用接口
  return {
    strategyFunction(type, price) {
      return strategy[type] && strategy[type](price)
    },
    // 添加算法
    addStrategy(type, fn){
      strategy[type] = fn
    }
  }
}()

priceceStrategy.strategyFunction('return30', 100)   // 130
priceceStrategy.strategyFunction('return50', 100)   // 150
priceceStrategy.strategyFunction('price80', 100)    // 80
priceceStrategy.strategyFunction('price90', 100)    // 90
// 添加一個算法
priceceStrategy.addStrategy('return70', (price) => {
  return price + parseInt(price / 100) * 70
})
console.log(priceceStrategy.strategyFunction('return70', 100))  // 170

還有我們的表單驗證也可以使用策略模式

// 定義一個策略對象
let inputStrategy = function(){
  // 內部算法對象 
  let strategy = {
    notNull(value){
      return /\s+/.test(value) ? '請輸入內容' : ''
    },
    number(value){
      return /^[0-9]+(\.[0-9]+)?$/.test(value) ? '' : '請輸入數字'
    }
  }
  // 策略方法調用接口
  return {
    check(type, value) {
      // 去除空白符
      value = value.replace(/^\s+|\s+$/g, '')
      return strategy[type] && strategy[type](value)
    },
    // 添加策略
    addStrategy(type, fn){
      strategy[type] = fn
    }
  }
}()

// 添加算法
inputStrategy.addStrategy('nickName', (value) => {
  return /^[a-zA-Z]\w{3,7}$/.test(value) ? '' : '請輸入4-8為昵稱'    
})

總結

策略模式屬於對象行為型模式,主要針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響 到客戶端的情況下發生變化。通常,策略模式適用於當一個應用程序需要實現一種特定的服務或者功能,而且該程序有多種實現方式時使用。

策略模式中的三個對象:

  • 環境對象:該類中實現了對抽象策略中定義的接口或者抽象類的引用。
  • 抽象策略對象:它可由接口或抽象類來實現。
  • 具體策略對象:它封裝了實現同不功能的不同算法。

利用策略模式構建應用程序,可以根據用戶配置等內容,選擇不同有算法來實現應用程序的功能。具體的選擇有環境對象來完成。采用這種方式可以避免由於使用條件語句而帶來的代碼混亂,提高應用程序的靈活性與條理性。

優點:
  1. 優化多重條件判斷,采用策略模式是的算法更利於維護
  2. 可擴展性,策略模式提供了對“開閉原則”的完美支持,用戶可以在不修改原有系統的基礎上選擇算法或行為,也可以靈活地增加新的算法或行為。
  3. 策略類之間可以自由切換,由於策略類都實現同一個接口,所以使它們之間可以自由切換。
缺點:
  1. 由於選擇哪種算法的決定權在用戶,所以對用戶來說就必須了解每種算法的實現。
  2. 由於每種算法間相互獨立,這樣對於一些復雜的算法處理相同邏輯的部分無法實現共享,這就會造成一些資源的浪費。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM