JS每日一題:設計模式-如何理解職責鏈模式?

20190412期

設計模式-如何理解職責鏈模式?後端

定義: 使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係,將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止

也就是說,請求之後,從第一個對象開始,鏈中收到請求的對象要麼親自處理它,要麼轉發給鏈中的下一個候選者。提交請求的對象並不明確知道哪個對象將會處理它——也就是該請求有一個隱式的接受者(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(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點推送當天的參考答案

  • 注 毫不僅限於完成當天任務,更可能是查漏補缺,學習羣內其它同窗優秀的答題思路

點擊加入答題

相關文章
相關標籤/搜索