JS每日一題:設計模式-如何理解職責鏈模式?
20190412期
設計模式-如何理解職責鏈模式?
定義: 使多個物件都有機會處理請求,從而避免請求的傳送者和接收者之間的耦合關係,將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個物件處理它為止
也就是說,請求以後,從第一個物件開始,鏈中收到請求的物件要麼親自處理它,要麼轉發給鏈中的下一個候選者。提交請求的物件並不明確知道哪一個物件將會處理它——也就是該請求有一個隱式的接受者(implicit receiver)。根據執行時刻,任一候選者都可以響應相應的請求,候選者的數目是任意的,你可以在執行時刻決定哪些候選者參與到鏈中
還不明白?ok, 來個生活小例項, 早高峰擠公交車,往往擠上去卻看不到售票員,我們常常通過他人之手將票錢傳遞給售票員,這種關係就能看做為職責鏈,我們的票錢通過多人之手最終遞交到售票員手中
程式碼場景:
假設我們正在開發一個電商網站,某一個商品正在進行預定活動,活動規則如下
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函式會隨著業務的變更經常修改
下面我們用職責鏈模式進行改寫
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(Aspect Oriented Programming )實現職責鏈
用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每日一題
JS每日一題可以看成是一個語音答題社群
每天利用碎片時間採用60秒內的語音形式來完成當天的考題
群主在次日0點推送當天的參考答案
- 注 絕不僅限於完成當天任務,更多是查漏補缺,學習群內其它同學優秀的答題思路