設計模式-如何理解職責鏈模式?後端
定義: 使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係,將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止
也就是說,請求之後,從第一個對象開始,鏈中收到請求的對象要麼親自處理它,要麼轉發給鏈中的下一個候選者。提交請求的對象並不明確知道哪個對象將會處理它——也就是該請求有一個隱式的接受者(implicit receiver)。根據運行時刻,任一候選者均可以響應相應的請求,候選者的數目是任意的,你能夠在運行時刻決定哪些候選者參與到鏈中設計模式
還不明白?ok, 來個生活小實例, 早高峯擠公交車,每每擠上去卻看不到售票員,咱們經常經過他人之手將票錢傳遞給售票員,這種關係就能看作爲職責鏈,咱們的票錢經過多人之手最終遞交到售票員手中app
代碼場景:
假設咱們正在開發一個電商網站,某一個商品正在進行預約活動,活動規則以下函數
500 元定金會收到200 優惠劵
200 元定金會收到100 優惠劵
沒有預約的用戶只能普通購買
假設咱們後端會返回以下字段性能
orderType [1,2,3] 分別爲500,200,普通購買學習
常規實現:網站
const order = function(orderType){ if(orderType===1){ // 假設咱們有其它需求 if(....){ ..... } return console.log(500元定金用戶) } if(orderType===2){ // 假設咱們有其它需求 if(....){ ..... } return console.log(200元定金用戶) } if(orderType===3){ // 假設咱們有其它需求 if(....){ ..... } return console.log(用戶普通購買) } } order(1) // 500元定金用戶
雖然咱們獲得了意料中的運行結果,但這並非一段優秀的代碼,order函數會隨着業務的變動常常修改this
下面咱們用職責鏈模式進行改寫prototype
const Chain = function(fn){ this.fn = fn; this.successor = null; } Chain.prototype.setNextSuccessor = function(successor){ 指定在鏈中的下一個節點 return this.successor = successor; } Chain.prototype.passRequest = function(){ //傳遞請求給某一下節點 var ret = this.fn.apply(this,arguments); if(ret === false){ // 若是ret 爲false 表明鏈條還得繼續往下走 return this.successor && this.successor.passRequest.apply(this.successor,arguments) } } // 包裝成職責鏈的節點 var chainOrder500 = new Chain(order500); var chainOrder200 = new Chain(order200); // 而後再指定節點在鏈中的順序 chainOrder500.setNextSuccessor(chainOrder200) // 最後把請求傳遞給第一個節點 chainOrder500.passRequest(1) // 500元定金用戶
用AOP實現職責鏈又簡單又巧妙,但這種函數疊加在一塊兒的方式,同時也疊加了函數的做用域,若是鏈條太長也會對性能形成影響設計
Function.prototype.after(fn){ var _this = this; return function(){ var ret = _this.apply(this,arguments); if(ret === false){ return fn.apply(this.arguments); } return ret } } var order = order500.after(order200).after(orderNormal); order(2) // 200定金用戶
職責鏈模式能夠很好的幫助咱們管理代碼,下降發起請求的對象跟接收請求對象的耦合,職責鏈中的節點順序是可變化的,咱們能夠在運行中決定鏈中包含哪些節點
JS每日一題能夠當作是一個語音答題社區
天天利用碎片時間採用60秒內的語音形式來完成當天的考題
羣主在第二天0點推送當天的參考答案