在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 設計模式之職責鏈模式
代碼復用模式(避免篇)
S.O.L.I.D 五大原則之接口隔離原則 ISP
設計模式之狀態(tài)模式
JavaScript 核心(晉級高手必讀篇)
設計模式之建造者模式
JavaScript 與 DOM(上)——也適用于新手
設計模式之中介者模式
設計模式之裝飾者模式
設計模式之模板方法
設計模式之外觀模式
強大的原型和原型鏈
設計模式之構造函數(shù)模式
揭秘命名函數(shù)表達式
深入理解J avaScript 系列(結局篇)
執(zhí)行上下文(Execution Contexts)
函數(shù)(Functions)
《你真懂 JavaScript 嗎?》答案詳解
設計模式之適配器模式
設計模式之組合模式
設計模式之命令模式
S.O.L.I.D 五大原則之單一職責 SRP
編寫高質量 JavaScript 代碼的基本要點
求值策略
閉包(Closures)
對象創(chuàng)建模式(上篇)
This? Yes,this!
設計模式之代理模式
變量對象(Variable Object)
S.O.L.I.D 五大原則之里氏替換原則 LSP
面向對象編程之一般理論
設計模式之單例模式
Function 模式(上篇)
S.O.L.I.D 五大原則之依賴倒置原則 DIP
設計模式之迭代器模式
立即調用的函數(shù)表達式
設計模式之享元模式
設計模式之原型模式
根本沒有“JSON 對象”這回事!
JavaScript 與 DOM(下)
面向對象編程之 ECMAScript 實現(xiàn)
全面解析 Module 模式
對象創(chuàng)建模式(下篇)
設計模式之職責鏈模式
S.O.L.I.D 五大原則之開閉原則 OCP
設計模式之橋接模式
設計模式之策略模式
設計模式之觀察者模式
代碼復用模式(推薦篇)
作用域鏈(Scope Chain)
Function 模式(下篇)
設計模式之工廠模式

設計模式之職責鏈模式

介紹

職責鏈模式(Chain of responsibility)是使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接受者之間的耦合關系。將這個對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理他為止。

也就是說,請求以后,從第一個對象開始,鏈中收到請求的對象要么親自處理它,要么轉發(fā)給鏈中的下一個候選者。提交請求的對象并不明確知道哪一個對象將會處理它——也就是該請求有一個隱式的接受者(implicit receiver)。根據(jù)運行時刻,任一候選者都可以響應相應的請求,候選者的數(shù)目是任意的,你可以在運行時刻決定哪些候選者參與到鏈中。

正文

對于 JavaScript 實現(xiàn),我們可以利用其原型特性來實現(xiàn)職責鏈模式。

var NO_TOPIC = -1;
var Topic;
function Handler(s, t) {
    this.successor = s || null;
    this.topic = t || 0;
}
Handler.prototype = {
    handle: function () {
        if (this.successor) {
            this.successor.handle()
        }
    },
    has: function () {
        return this.topic != NO_TOPIC;
    }
};

Handler 只是接受 2 個參數(shù),第一個是繼任者(用于將處理請求傳下去),第二個是傳遞層級(可以用于控制在某個層級下是否執(zhí)行某個操作,也可以不用),Handler 原型暴露了一個 handle 方法,這是實現(xiàn)該模式的重點,先來看看如何使用上述代碼。

    var app = new Handler({
        handle: function () {
            console.log('app handle');
        }
    }, 3);
    var dialog = new Handler(app, 1);
    var button = new Handler(dialog, 2);
    button.handle();

改代碼通過原型特性,調用代碼從 button.handle()->dialog.handle()->app.handle()->參數(shù)里的 handle(),前三個都是調用原型的 handle,最后才查找到傳入的參數(shù)里的 handle,然后輸出結果,也就是說其實只有最后一層才處理。

那如何做到調用的時候,只讓 dialog 的這個對象進行處理呢?其實可以定義 dialog 實例對象的 handle 方法就可以了,但需要在 new button 的之前來做,代碼如下:

    var app = new Handler({
        handle: function () {
            console.log('app handle');
        }
    }, 3);
    var dialog = new Handler(app, 1);
    dialog.handle = function () {
        console.log('dialog before ...')
        // 這里做具體的處理操作
        console.log('dialog after ...')
    };
    var button = new Handler(dialog, 2);
    button.handle();

該代碼的執(zhí)行結果即時 dialog.handle 里的處理結果,而不再是給 app 傳入的參數(shù)里定義的 handle 的執(zhí)行操作。

那能不能做到自身處理完以后,然后在讓繼任者繼續(xù)處理呢?答案是肯定的,但是在調用的 handle 以后,需要利用原型的特性調用如下代碼:

Handler.prototype.handle.call(this);

該句話的意思說,調用原型的 handle 方法,來繼續(xù)調用其繼任者(也就是 successor )的 handle 方法,以下代碼表現(xiàn)為:button/dialog/app 三個對象定義的 handle 都會執(zhí)行。

var app = new Handler({
    handle: function () {
        console.log('app handle');
    }
}, 3);
var dialog = new Handler(app, 1);
dialog.handle = function () {
    console.log('dialog before ...')
    // 這里做具體的處理操作
    Handler.prototype.handle.call(this); //繼續(xù)往上走
    console.log('dialog after ...')
};
var button = new Handler(dialog, 2);
button.handle = function () {
    console.log('button before ...')
    // 這里做具體的處理操作
    Handler.prototype.handle.call(this);
    console.log('button after ...')
};
button.handle();

通過代碼的運行結果我們可以看出,如果想先自身處理,然后再調用繼任者處理的話,就在末尾執(zhí)行 Handler.prototype.handle.call(this); 代碼,如果想先處理繼任者的代碼,就在開頭執(zhí)行 Handler.prototype.handle.call(this); 代碼。

總結

職責鏈模式經(jīng)常和組合模式一起使用,這樣一個構件的父構件可以作為其繼任者。

同時,DOM 里的事件冒泡機制也和此好像有點類似,比如點擊一個按鈕以后,如果不阻止冒泡,其 click 事件將一直向父元素冒泡,利用這個機制也可以處理很多相關的問題,比如本系列設計模式享元模式里的《例1:事件集中管理》的示例代碼。