設計模式之職責鏈模式

前言

職責鏈模式在咱們的開發中很是常見,然而在不知道的同窗那裏,可能你以前都是經過if/else的方式來實現的相似邏輯。職責鏈主要就是指,在執行一個具體的事情時,不肯定使用哪一種邏輯時,進行鏈式的判斷,直到找到符合條件的函數或者對象,而後處理。分析,發現其實咱們不少的代碼的背後邏輯就是職責鏈模式。javascript

圖解

image.png

現實中的職責鏈

現實中的例子很是多,好比,咱們在擠公交時,若是人特別多,咱們以前是將硬幣經過人傳遞的方式,依次向前傳遞,直到前面的人是司機或者售票員,這就是一個很是明顯的職責鏈的例子。java

代碼重構

原先的代碼主要是經過if,else進行不斷的判斷,執行不一樣的邏輯。設計模式

案例說明

image.png

重構前

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('庫存不足')
      }
   }
}
複製代碼

重構後

咱們按照職責鏈的設計思想,一步到位,分別包含如下的思路:app

  • 將不一樣的購買模式封裝爲函數
  • 實現鏈式函數,能夠不斷追加函數,能夠在不符合時,實現遞交
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);
複製代碼

codepen地址:codepen.io/robinson90/…函數

番外篇:職責驅動設計以及狀態模式的實踐

文章連接:mp.weixin.qq.com/s/qQEEnf79F…學習

需求

image.png

解決方案

引入職責驅動概念,從知識的能力的角度,去判斷哪一個對象具備操做的能力。ui

但這樣的壞處是當加入新的狀態時,全部實現接口的狀態類都須要變動,不符合設計模式的開閉原則。this

狀態圖:spa

image.png

image.png

另外一種"職責鏈"

這種不在典型的職責鏈設計中,是我我的在開發過程當中,本身認爲的也符合形式上的鏈式判斷,但最終只肯定執行一個最終函數,而不是實現鏈式遞交的。prototype

固然了,也可能這徹底不屬於任何一種設計模式,不過我以爲設計模式的本質仍是爲了解決固定場景的固定思惟模式,至於叫什麼名字應該不是重點。

具體代碼以下:

let Chain = function(){
  let dutyArr = []
	this.addDuty = function(duty){
    dutyArr.push(duty)
  }
  this.opt = function(params){
		for(let index in dutyArr){
    	if(dutyArr[index].judge(params)){
      	return dutyArr[index].opt && dutyArr[index].opt(params);
      }
    } 
    return false
  }
}

let ageChainDemo = new Chain();
ageChainDemo.addDuty({
	judge:function(params){
    let {age} = params;
    return age > 18;
},
  opt:function(params){
    let {age} = params;
    return '你已是成年人了'
  }
})

ageChainDemo.addDuty({
	judge:function(params){
    let {age} = params;
    return age > 0 && age < 18;
},
  opt:function(params){
    let {age} = params;
    return '你仍是未成年'
  }
})
let result = ageChainDemo.opt({age:20});
console.log(result);
let result2 =ageChainDemo.opt({age:10});
console.log(result2);
複製代碼

codepen地址:codepen.io/robinson90/…

與策略模式的區別

乍一看,寫法上,職責鏈與策略模式沒什麼,都是分別維護不一樣的函數邏輯,其區別主要是使用條件的判斷。

策略模式能夠準確的決定使用哪一種策略,並且能夠肯定使用這種策略就能返回結果;而職責鏈模式,則是將使用條件進行抽象,內置到函數中,經過不斷的函數內部判斷,若是不符合,須要繼續判斷傳遞,直到執行到符合條件的函數並執行。

由此,咱們能夠這樣斷定,若是咱們對條件屬於模糊的,更適合使用職責鏈。這樣要好於寫if/else內寫複雜的布爾運算,或者使用某個計算變量的結果值,或者使用其餘函數的返回結果。

更多

原文連接:www.yuque.com/robinson/de…

更多設計模式的學習與瞭解,能夠移步到個人設計模式專輯:www.yuque.com/robinson/de…

相關文章
相關標籤/搜索