1. 程式人生 > >責任鏈模式 詳解

責任鏈模式 詳解

定義

是一種物件的行為模式,在責任鏈模式裡,很多物件由每個對其下家的引用而連線起來形成的一條鏈,請求在這個鏈上傳遞,直到鏈上的某一個物件決定處理此請求,發出這個請求的客戶端並不知道鏈上的哪一個物件最終會處理這個請求;

行為型模式

角色

  • 抽象處理者角色(Handler):定義處理請求的介面;
  • 抽象處理者角色(ConcreteHandler):具體處理者接到請求後,可以選擇處理該請求或者傳遞給下家;

從網上找到的例圖
enter image description here

適用場景

  • 有多個物件可以處理一個請求,哪個物件處理該請求執行時刻自動確定;
  • 在不確定指定接收者的情況下,向多個物件中的一個提交一個請求;
  • 處理一個請求的物件集合應被動態繫結;

例子

  • 這個很像傳遞遊戲,需要將東西傳遞個下一個人,只有在當音樂停止的時候才知道下個執行者是誰;

實現程式碼

/**
 * Created by George on 16/7/14.
 */
/**
 * Created by George on 16/7/15.
 */

var Levels = {
    smallBoss : 1,
    middleBoss : 2,
    bigBoss : 3
};

var AbstractRequest = function (content) {
    this.content = content;
    this
.getContent = function () { return this.content; }; this.getRequestLevel = function () { }; }; var Request01 = function (content) { this.content = content; AbstractRequest.call(this, content); this.getRequestLevel = function () { return Levels.smallBoss; }; }; var
Request02 = function (content) { this.content = content; AbstractRequest.call(this, content); this.getRequestLevel = function () { return Levels.middleBoss; }; }; var Request03 = function (content) { this.content = content; AbstractRequest.call(this, content); this.getRequestLevel = function () { return Levels.bigBoss; }; }; var AbstractHandler = function () { // 下個責任處理者 this.nextHandler = null; // 捕獲具體請求,並將責任傳遞給下個責任處理者 this.handleRequest = function (request) { // 層級相同 if (this.getHandlerLevel() == request.getRequestLevel()) this.handle(request); else { if (this.nextHandler != null) { console.log("當前處理者層級" + this.getHandlerLevel() + "\n" + "不足以處理請求" + request.getRequestLevel()); // 遞迴 this.nextHandler.handleRequest(request); } else { console.log("鏈上所有處理者都不能處理該請求"); } } }; // 設定責任鏈的下個處理者 this.setNextHandler = function (nextHandler) { this.nextHandler = nextHandler; }; // 獲取當前處理者的級別 this.getHandlerLevel = function () { }; // 定義鏈中每個處理者具體的處理方式 this.handle = function (request) { }; }; // 具體處理者1 var Handler01 = function () { }; Handler01.prototype = new AbstractHandler(); Handler01.prototype.getHandlerLevel = function () { return Levels.smallBoss; }; Handler01.prototype.handle = function (request) { console.log("small boss 處理" + request.getContent() + "\n"); }; // 具體處理者2 var Handler02 = function () { }; Handler02.prototype = new AbstractHandler(); Handler02.prototype.getHandlerLevel = function () { return Levels.middleBoss; }; Handler02.prototype.handle = function (request) { console.log("middle boss 處理" + request.getContent() + "\n"); }; // 具體處理者3 var Handler03 = function () { }; Handler03.prototype = new AbstractHandler(); Handler03.prototype.getHandlerLevel = function () { return Levels.bigBoss; }; Handler03.prototype.handle = function (request) { console.log("big boss 處理" + request.getContent() + "\n"); }; // 建立結點 var handler01 = new Handler01(); var handler02 = new Handler02(); var handler03 = new Handler03(); // 組裝鏈 handler01.setNextHandler(handler02); handler02.setNextHandler(handler03); // 建立請求 var request01 = new Request01("請求1"); var request02 = new Request02("請求2"); var request03 = new Request03("請求3"); // 每次提交都要從鏈頭開始遍歷 handler01.handleRequest(request01); handler01.handleRequest(request02); handler01.handleRequest(request03);

實現結果:

這裡寫圖片描述
這裡面注意的是,設定處理的條件為其等級相同,也就是相互對應,不能越級處理,也不能低階處理;

優缺點

  1. 降低耦合度,一個物件無需知道哪個物件處理其請求,物件僅知道該請求會被正確處理,接受者和傳送者 都沒有對方的明確的資訊;
  2. 簡化物件的相互連線,僅僅需要保持一個指向其後繼者的引用,而不需要保持他所有的候選者的引用;
  3. 增強了給物件指派職責的靈活性,當在物件中分派職責時,職責鏈給你更多的靈活性,可以通過在執行時刻對該鏈進行動態的增加或者修改來增加或改變一個請求的職責,可以將這種機制和靜態的特例化處理物件的繼承機制結合起來使用;
  4. 增加新的請求處理類方便;

注意的是
1. 對於每個請求都需要遍歷職責鏈,當數量大了以後可能會有效能問題;
2. 不能保證請求一定會被接收;