W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
職責(zé)鏈模式(Chain of responsibility)是使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接受者之間的耦合關(guān)系。將這個對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理他為止。
也就是說,請求以后,從第一個對象開始,鏈中收到請求的對象要么親自處理它,要么轉(zhuǎn)發(fā)給鏈中的下一個候選者。提交請求的對象并不明確知道哪一個對象將會處理它——也就是該請求有一個隱式的接受者(implicit receiver)。根據(jù)運行時刻,任一候選者都可以響應(yīng)相應(yīng)的請求,候選者的數(shù)目是任意的,你可以在運行時刻決定哪些候選者參與到鏈中。
對于JavaScript實現(xiàn),我們可以利用其原型特性來實現(xiàn)職責(zé)鏈模式。
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();
改代碼通過原型特性,調(diào)用代碼從button.handle()->dialog.handle()->app.handle()->參數(shù)里的handle(),前三個都是調(diào)用原型的handle,最后才查找到傳入的參數(shù)里的handle,然后輸出結(jié)果,也就是說其實只有最后一層才處理。
那如何做到調(diào)用的時候,只讓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í)行結(jié)果即時dialog.handle里的處理結(jié)果,而不再是給app傳入的參數(shù)里定義的handle的執(zhí)行操作。
那能不能做到自身處理完以后,然后在讓繼任者繼續(xù)處理呢?答案是肯定的,但是在調(diào)用的handle以后,需要利用原型的特性調(diào)用如下代碼:
Handler.prototype.handle.call(this);
該句話的意思說,調(diào)用原型的handle方法,來繼續(xù)調(diào)用其繼任者(也就是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();
通過代碼的運行結(jié)果我們可以看出,如果想先自身處理,然后再調(diào)用繼任者處理的話,就在末尾執(zhí)行Handler.prototype.handle.call(this);代碼,如果想先處理繼任者的代碼,就在開頭執(zhí)行Handler.prototype.handle.call(this);代碼。
職責(zé)鏈模式經(jīng)常和組合模式一起使用,這樣一個構(gòu)件的父構(gòu)件可以作為其繼任者。
同時,DOM里的事件冒泡機制也和此好像有點類似,比如點擊一個按鈕以后,如果不阻止冒泡,其click事件將一直向父元素冒泡,利用這個機制也可以處理很多相關(guān)的問題,比如本系列設(shè)計模式享元模式里的《例1:事件集中管理》的示例代碼。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: