摘要:想一想,這個和我們的迭代器模式有著異曲同工的妙處,迭代器模式同樣也是遍歷選出最優(yōu)解,但是相比而言,職責鏈模式的直觀性個書寫的幸福感是遠遠超過迭代器模式的。
職責鏈模式其實很好理解,由于一個鏈字出賣了它的靈魂。我們可以從這個字得到很大的提示。首先這個模式一定有傳遞性,而且,節(jié)點是可以重復拼接的,并且每個節(jié)點都具有一定的過濾功能,一定的職責。
是不是想起了組合模式里的一些內(nèi)容呢? 是的,他們兩個有著天然的類似點,不過組合模式主要職責是給執(zhí)行者添加一些列行為,而不區(qū)分內(nèi)部的執(zhí)行。職責鏈模式則會強調(diào)內(nèi)部的細節(jié),他可以手動傳遞權(quán)限,手動終止權(quán)限。
舉個栗子吧:
小時候,俺是一個學渣,平時作業(yè)都不會做,但是老師硬性要求你做。沒辦法,只有去借鑒學霸的作業(yè)。首先,我們班人都超級好,我做在最后一排,然后
我問前一排的妹紙: 嗨,小芳,你的作業(yè)能給我看看嘛? 小芳: 我作業(yè)沒做呢?我?guī)湍銌枂柷懊娴摹?小芳: 小明,你作業(yè)做完了嗎?能給我看看嘛? 小明: 我作業(yè)沒做呢?我?guī)湍銌枂柷懊娴摹?小明: 小吉,你作業(yè)做完了嗎?能給我看看嘛? 小吉: 做完了,給你吧。
恩,good,事情圓滿解決。完美的體現(xiàn)出,職責鏈的內(nèi)涵,上一節(jié)點,只要知道下一個節(jié)點的接口,so that enough。 如果本身節(jié)點能夠完成任務(wù),則將結(jié)果輸出,終止傳遞。
用代碼標識即為:
function Me (flag){ if(flag===1){ console.log("I can do this homeword"); }else{ console.log("I can"t :(, but u can do this ?"); XiaoFang(flag); } } function XiaoFang (flag){ if(flag===1){ console.log("I can do this homeword"); }else{ console.log("I can"t :(, but u can do this ?"); XiaoJi(flag); } } function XiaoJi (flag){ if(flag===0){ console.log("I can do this homeword"); }else{ console.log("I can"t :(, but u can do this ?"); //...繼續(xù)詢問下一個人 } } Me(0);
沒錯,職責鏈的主要內(nèi)涵就是,如果你不行,在問問下一個人行不行。。。但是上面代碼讓我有種想kill people的沖動(不是寫的爛,是寫的太爛了),唯一能夠表揚他的就是,知道職責鏈模式的原理。所以為了情懷,我們需要給上面的代碼換一身皮.
function Chain(fn){ this.fn = fn; this.nextExer = null; } Chain.prototype.setNext = function(obj){ this.nextExer = obj; } Chain.prototype.exe = function(flag){ var result = this.fn.apply(this,arguments); if(result === "next"){ this.next(flag); } } Chain.prototype.next = function(){ return this.nextExer.exe.apply(this.nextExer,arguments) } var fn1 = new Chain(function(flag){ if(flag===1){ console.log("I can do this homework"); }else{ console.log("I can"t do this homework"); return "next"; } }); var fn2 = new Chain(function(flag){ if(flag===1){ console.log("I can do this homework"); }else{ console.log("I can"t do this homework"); return "next"; } }) var fn3 = new Chain(function(flag){ if(flag===0){ console.log("I can do this homework"); }else{ console.log("I can"t do this homework"); return "next"; } }) fn1.setNext(fn2); fn2.setNext(fn3); fn1.exe(0);
雖然,上面這段代碼看起來清晰很多,使用next調(diào)用下一個函數(shù),使用exe初始化.但是看起來在setNext哪里有點啰嗦。我們試著改進:
Chain.prototype.setNext = function(obj){ this.nextExer = obj; return obj; } fn1.setNext(fn2).setNext(fn3); fn1.exe(0);
只需要將setNext哪里返回一個Obj,就可以得到完美的鏈式調(diào)用了。可以從上面的代碼中看出一些端倪,在職責鏈模式中,我們需要規(guī)定,在每個exe執(zhí)行過后需要設(shè)置一個result,并且這個result必須能明確的標識下一個到底繼不繼續(xù)。
當然,要知道,這個職責鏈模式并不是一定要把管理權(quán)交給內(nèi)部執(zhí)行,你當然也可以在外面進行判斷和設(shè)置。
var fn2 = new Chain(function(flag){ console.log("I can"t do this homework"); this.nextExer.fn(0); //手動執(zhí)行下一個 })
通過上面的步驟,可以在外部直接判斷,是否執(zhí)行下一個。所以職責模式的寫法也是很多的。
職責鏈的利弊而且,職責鏈最大的一個好處就是,你可以從鏈中,任意一個節(jié)點開始遍歷。 我們用上面那個例子體會一下。
假如,我前面座的童鞋,我和他都同時喜歡一女生,所以我倆關(guān)系超差。我當然不能問情敵要作業(yè)啦,這時候,我可以再往前一個同學問。利用職責模式就為.
xiaoMing.setNext(xiaoFang).setNext(xiaoJi); //改寫,直接從小芳開始 xiaoFang.setNext(xiaoJi);
這應(yīng)該算是職責鏈模式的一大特色,但是這個也不是沒有問題的,就是我們需要在最后一個節(jié)點上加上判斷,表示如果沒有其他處理程序,而且在該節(jié)點上也不成立的話,則需要拋出一個錯誤,或者做出相應(yīng)的說明. 并且,我們每次請求的時候,都會從節(jié)點鏈的開始進行遍歷,這樣很可能會造成性能的損失,所以這里需要注意的是,不要設(shè)置太長的職責鏈。
使用AOP這里AOP指的是面向切面編程,即將其他函數(shù)動態(tài)的加入到一個函數(shù)中,比如before & after. 我們仔細想想,一個隊列無外乎就是在前在后的關(guān)系,所以一個before和after已經(jīng)算是萬能的了(排除你有動態(tài)刪除的需求)。
Function.prototype.after = function(fn){ var _this = this; return function(){ var res = _this.apply(this,arguments); if(!res){ //值為Boolean return fn.apply(this,arguments); } return res; } } Function.prototype.before = function(fn){ var _this = this; return function(){ fn.apply(this,arguments); return _this.apply(this,arguments); } }
上面已經(jīng)將AOP中兩個最重要的before和after添加到Function的原型里面了。
現(xiàn)在我們可以使用這兩把三相之力開啟職責鏈模式
XiaoMing.after(XiaoFang).after(XiaoJi);
我操,完美啊,通俗易懂哎喂。
如果我們需要加上判斷的話,可以直接在after和before里面寫
//只舉before的例子吧 Function.prototype.before = function(fn){ var _this = this; return function(){ var res = fn.apply(this,arguments); //值為Boolean,表示是否繼續(xù)向下傳遞 if(res===false){ //如果返回不成立,則繼續(xù)向下傳遞 return _this.apply(this,arguments); } } } function Xiaoming(){ console.log("I can do this homework"); return "ok"; //中斷返回,當然這里你可以隨便定義,除了"next" } function XiaoFang(){ console.log("I can"t do this homework"); return "next"; } Xiaoming. before(XiaoFang)();職責鏈模式之干貨
我們這里再次回憶一下職責鏈模式的用處,將一個請求依照一條鏈傳遞,如果有個滿足則斷開傳遞,返回結(jié)果。 想一想,這個和我們的迭代器模式有著異曲同工的妙處,迭代器模式同樣也是遍歷選出最優(yōu)解,但是相比而言,職責鏈模式的直觀性個書寫的幸福感是遠遠超過迭代器模式的。
在寫一些hacks的時候,難免會用到if...else if...判斷語句,上次我們使用迭代器模式完成這樣的功能,但是效果不是很理想,這里我們使用職責鏈模式完成。
事件模式的選擇函數(shù)
Function.prototype.after = function(fn){ var _this = this; return function(){ var res = _this.apply(this,arguments); if(res==="next"){ //值為Boolean return fn.apply(this,arguments); } return res; } } var bind = (function() { var DOM2 = function() { if (document.addEventListener) { return function(ele, fn, type) { ele.addEventListener(type, () => { fn(); }, false); } } else { return "next"; } }; var IE = function() { if (document.attachEvent) { return function(ele, fn, type) { ele.attachEvent(type, fn); } } else { return "next"; } }; var DOM0 = function(){ return function(ele, fn, type) { ele[`on${type}`] = () => { fn(); }; } } return DOM2.after(IE).after(DOM0)(); })(); console.log(bind);
恩,以上結(jié)果只是一個簡單地示范。 這里需要提個醒,職責鏈模式是設(shè)計模式中最容易忘記的模式之一,因為它好用到不叫模式。所以,職責鏈模式的用法也是很多的,希望大家多多探索,將自己學到的只是分享出來,這是,極好的呀!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/78510.html
摘要:簡介職責鏈模式有時候也叫責任鏈模式,它是一種對象行為的設(shè)計模式。中的就是使用了責任鏈模式。純的責任鏈模式的實際例子很難找到,一般看到的例子均是不純的責任鏈模式的實現(xiàn)。如果堅持責任鏈不純便不是責任鏈模式,那么責任鏈模式便不會有太大意義了。 Java設(shè)計模式之職責鏈模式 前幾天復習java的異常處理時,接觸到了責任鏈模式。在企業(yè)級應(yīng)用中,從前臺發(fā)過來的請求在后臺拋出異常,異常處理的設(shè)計一般...
摘要:提交請求的對象并不明確知道哪一個對象將會處理它也就是該請求有一個隱式的接受者。 20190412期 設(shè)計模式-如何理解職責鏈模式? 定義: 使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接收者之間的耦合關(guān)系,將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止 也就是說,請求以后,從第一個對象開始,鏈中收到請求的對象要么親自處理它,要么轉(zhuǎn)發(fā)給鏈中的下一個候選者。提...
摘要:使用面向切面編程來快速的創(chuàng)建職責鏈的具體概念可以參考裝飾者模式實現(xiàn)職責鏈簡單又巧妙,但這種把函數(shù)疊在一起的方式,同時也疊加了函數(shù)的作用域,如果鏈條太長的話,也會對性能造成太大的影響。在開發(fā)中,職責鏈模式是最容易被忽視的模式之一。 聲明:這個系列為閱讀《JavaScript設(shè)計模式與開發(fā)實踐》 ----曾探@著一書的讀書筆記 1.職責鏈模式的定義 2. 2.1 簡單職責鏈模式 2....
摘要:用實現(xiàn)職責鏈這里使用變量存儲上一個函數(shù),存儲的是最后一個調(diào)用返回的函數(shù)。理解了過程也就會知道這句代碼是為后面的函數(shù)準備的建議如果某塊功能中存在大量的可以考慮使用職責鏈模式 職責鏈模式 1. 職責鏈定義 使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接受者之間的耦合關(guān)系,將對象連成一條鏈,并沿著這個鏈傳遞該請求,直到有一個對象處理它為止 2.職責鏈優(yōu)點 請求發(fā)送者只需要知道鏈中的第一...
摘要:責任鏈模式屬于行為型模式的一種,將請求沿著一條鏈傳遞,直到該鏈上的某個對象處理它為止。責任鏈模式通過將請求和處理分離開來,以進行解耦。源碼分析我們經(jīng)常使用的就使用到了責任鏈模式,創(chuàng)建一個除了要在應(yīng)用中做相應(yīng)配置外,還需要實現(xiàn)接口。 責任鏈模式(Chain Of Responsibility Pattern)屬于行為型模式的一種,將請求沿著一條鏈傳遞,直到該鏈上的某個對象處理它為止。 ...
閱讀 1193·2021-11-15 18:00
閱讀 1789·2021-10-08 10:15
閱讀 752·2021-09-04 16:48
閱讀 2373·2021-09-04 16:48
閱讀 1313·2019-08-29 18:40
閱讀 965·2019-08-29 13:08
閱讀 2987·2019-08-26 14:06
閱讀 1111·2019-08-26 13:35