設計模式之職責鏈模式vs策略模式

學習背景

  1. 針對if/if…else語句,或者switch...case 的衆多使用的重構
  2. 函數、組件設計的思考

什麼是職責鏈模式(責任鏈模式)?

爲了不請求發送者與多個請求處理者耦合在一塊兒,將全部請求的處理者經過前一對象記住其下一個對象的引用而連成一條鏈;當有請求發生時,可將請求沿着這條鏈傳遞,直到有對象處理它爲止。(簡言:一個請求有多個對象能夠處理,但每一個對象的處理條件或權限不一樣。)
主要構成者:
  1. 抽象處理者(handler):後繼處理鏈接的接口
  2. 具體處理者(concrete handler):抽象處理者的具體實現方式,處理本次請求或者向後傳遞
  3. 客戶類(client):建立處理鏈,並向具體處理者對象提交請求,不關心內部發生了什麼

案例代碼1,公司促銷活動,返優惠券:算法

const order = (orderType,pay,stock) {  if(orderType === 1){    if(pay === true){      console.log('500元定金,返回100優惠券')    } else {      if(stock > 0 ){        consle.log('普通購買,無優惠券')      } else {        console.log('庫存不足')      }    }  } else if(orderType === 2){    if(pay === true){      console.log('200元定金,返回50優惠券')    } else {      if(stock > 0 ){        consle.log('普通購買,無優惠券')      } else {        console.log('庫存不足')      }    }              } else {    if(stock > 0 ){        consle.log('普通購買,無優惠券')      } else {        console.log('庫存不足')      }   }}複製代碼

職責鏈設計思想,重構思路
  • 將不一樣的購買模式單獨封裝成函數
  • 實現鏈式函數,支持追加函數;在不符合時,實現遞交

// 模式封裝,具體處理者const order500 = function(orderType,pay,stock){    if(orderType === 1 && pay === true){        console.log('500元定金,返回100優惠券')    } else {        return 'nextSuccessor';    }}const order200 = function(orderType,pay,stock){    if(orderType === 2 && pay === true){        console.log('200元定金,返回50優惠券')    } else {        return 'nextSuccessor';    }}const orderNormal = function(orderType,pay,stock){    if(stock > 0 ){        console.log('普通購買,無優惠券')      } else {        console.log('庫存不足')      }}// 原型鏈,鏈式傳遞,抽象處理者const Chain = function(fn){    this.fn = fn;    this.successor = null;}Chain.prototype.setNextSuccessor = function(successor){    return this.successor = successor;}Chain.prototype.passRequest = function(){ let ret = this.fn.apply(this, arguments); if(ret === 'nextSuccessor'){    return this.successor && this.successor.passRequest.apply(this.successor, arguments); } return ret;}// 組裝責任鏈let chainOrder500 = new Chain(order500);let chainOrder200 = new Chain(order200);let chainOrderNormal = new Chain(orderNormal);chainOrder500.setNextSuccessor(chainOrder200);chainOrder200.setNextSuccessor(chainOrderNormal);// 調用chainOrder500.passRequest(1,false,0);chainOrder500.passRequest(1,true,10);chainOrder500.passRequest(2,true,11);chainOrder500.passRequest(2,false,1);複製代碼

職責鏈模式關係圖bash


職責鏈模式總結app

  • 優勢:
    • 各司其職,符合類的最小封裝原則
    • 工做流程能夠自由組合
    • 類與類之間的低耦合
  • 缺點:
    • 具體處理者類太多,會影響執行效率
  • 注意:職責鏈創建的合理性


什麼是策略模式?

該模式定義了一系列算法,並將每一個算法封裝起來,使它們能夠相互替換,且算法的變化不會影響使用算法的客戶。策略模式屬於對象行爲模式,它經過對算法進行封裝,把使用算法的責任和算法的實現分割開來,並委派給不一樣的對象對這些算法進行管理。(簡言:把一系列的算法封裝起來,讓其能夠相互替換,封裝的算法具備必定的獨立性,不隨客戶端的變化而變化。)

主要構成者:函數

  1. 抽象策略類(Strategy):是一個公共接口,由不一樣的算法實現,環境類使用這個接口調用不一樣的算法
  2. 具體策略類(Concrete Strategy):具體算法的實現
  3. 環境類(Context):客戶端調用的一個策略類的引用

案例代碼2,產品促銷,按用戶等級返現:學習

return30(price) {    // 返現30 do something}retuen50(price) {    // do something}switch(user.cheaperLevel) {    case 1: return30()    break    case 2: return50()    break    ...}// 函數全局暴露,不能根據不一樣狀況去使用想要的方法複製代碼

策略模式設計重構ui

const PriceStrategy = function(){// 內部算法對象, 具體策略類    const stragtegy = {        return30: function(price){        },        return60: function(price){        },    }// 策略算法調用接口,抽象策略類    return function(cheaperLevel,price) {        return stragtegy[cheaperLevel] && stragtegy[cheaperLevel](price)    }}// 使用方式,環境類let price = PriceStrategy('return30','321.56')console.log(price)複製代碼

案例代碼3,表單驗證,策略模式重構:this

const inputStrategy = () => {    const strategy = {        notNull : (val) => {            return /\s+/.test(val) ? '請輸入' : '';        },        number :(val) => {            return val.isNaN ? '請輸入數字' :'';        }    }    return {        check:(type,value)=>{           return  strategy[type](value) ;        },        // 確定策略不夠用,爲它添加一個自定義的策略Api        addStrategy:(type,fn)=>{            strategy[type] = fn ;        }    }}// 算法調用let inputValue = document.getElmentById('target')let isVaild = inputStrategy.check('number',inputValue)複製代碼

策略模式總結spa

  • 優勢
    • 避免多重條件語句
    • 可複用
    • 開閉原則的完美支持,靈活增長新算法
    • 算法的使用和實現的分離
  • 缺點
    • 客戶端使用必須理解全部算法的區別(備註/註釋)
    • 有不少的策略類


二者之間的區別

職責鏈模式
  • 解決更多的是 條件屬於模糊的判斷,執行不一樣的邏輯,好比if(true || false) / else if() /…
  • 將判斷條件內置於函數中,條件不符合須要鏈式傳遞繼續執行函數
策略模式
  • 有肯定的判斷條件,好比switch...case
  • 直接根據肯定的判斷條件調用
相關文章
相關標籤/搜索