責(zé)任鏈Chain Of Responsibility

前言

寫(xiě)方法的原則要盡量做到一個(gè)方法只做一件事情济舆, 這樣做到職責(zé)單一抵怎, 日后對(duì)于代碼的維護(hù)也非常容易浓恶。 并且代碼的復(fù)用性也會(huì)很高玫坛。

在某些情況下, 對(duì)于某個(gè)事件或某個(gè)消息的處理是一個(gè)接一個(gè)的包晰, 而又不想以下這種寫(xiě)法

process(Message a){
    b = doSomethingA(a)
    c = doSomethingB(b)
    d = doSomethingC(c)
    e = doSomethingD(d)
}

以上這種寫(xiě)法很容易湿镀, 可以明顯看到執(zhí)行的順序,也可以保證一個(gè)方法只做一件事情伐憾, 讓后將這些事情連起來(lái)勉痴。

一些弊端

  1. 代碼不易維護(hù)
    假如在第二步中我們想改為多線程執(zhí)行, 則需要改動(dòng)process中的代碼树肃, 而針對(duì)職責(zé)鏈則僅需加入多線程節(jié)點(diǎn)來(lái)使得后續(xù)的處理變?yōu)槎嗑€程蒸矛。

  2. 調(diào)用關(guān)系的臃腫
    我們能看到, 上面代碼的調(diào)用是process作為調(diào)用方胸嘴, 連續(xù)調(diào)用a,b,c,d方法雏掠, process未必僅僅是調(diào)用a,b,c,d 。在程序種往往要進(jìn)行邏輯判斷劣像, 比如如果B方法的的返回值c為null磁玉, 則不再向后執(zhí)行,那么我們可能會(huì)在process方法種在后面加上該判斷

    if(c == null){
        return; 
    }

如果是更復(fù)雜的邏輯處理驾讲, 異常處理等蚊伞, 就需要在process方法種加入相應(yīng)的邏輯處理代碼, 從而使得代碼變得越來(lái)越臃腫吮铭。

換一種思路

這時(shí)候我們想时迫, 能否使得上一次的調(diào)用對(duì)下一次的調(diào)用負(fù)責(zé), 而不是通過(guò)process這層來(lái)管理谓晌, 如下圖顯示

職責(zé)鏈簡(jiǎn)圖

那么像這樣的如鏈?zhǔn)秸{(diào)用的機(jī)構(gòu)掠拳, 就叫做職責(zé)鏈。

其實(shí)在java中纸肉,已經(jīng)有很多地方遇到過(guò)它溺欧。

我們?cè)谀睦镆?jiàn)過(guò)職責(zé)鏈這種模式

  1. java web filter
    在java web開(kāi)發(fā)中, 最早的應(yīng)該就屬filter了
    實(shí)現(xiàn)Filter接口柏肪, 重寫(xiě)doFilter.
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chian) throws IOException, ServletException {
        chian.doFilter(...)
    }

如果接觸過(guò)socket編程姐刁, 對(duì)mina 或者netty框架熟悉的話, 責(zé)任鏈模式將更不陌生烦味。
在mina中:
通過(guò)FilterChianBuilder, FilterChain, IoFilter 構(gòu)成一個(gè)鏈聂使。 創(chuàng)建方式如下

DefaultIoFilterChainBuilder builder = new DefaultIoFilterChainBuilder();
builder.addFirst("mdcInjectionFilter", new MdcInjectionFilter(MdcInjectionFilter.MdcKey.remoteAddress));
builder.addAfter("mdcInjectionFilter", "codExecutorFilter", new ExecutorFilter());
builder.addAfter("codExecutorFilter", "loggingFilter", new LoggingFilter());
builder.addAfter("loggingFilter", "codecFilter", codecFilter);
builder.addAfter("codecFilter", "executorFilter", executorFilter);
builder.addAfter("executorFilter", "writeExecutorFilter", new ExecutorFilter(IoEventType.WRITE));
DefaultIoFilterChain chain = new DefaultIoFilterChain();
builder.buildFilterChain(chain);

這樣就構(gòu)造了一條職責(zé)鏈, 每一個(gè)節(jié)點(diǎn)負(fù)責(zé)下面一個(gè)節(jié)點(diǎn), 節(jié)點(diǎn)內(nèi)執(zhí)行一定的邏輯柏靶。 至于如何構(gòu)造職責(zé)鏈可以看我的mina源碼分析弃理。

  1. netty 中
    在netty中, 核心的業(yè)務(wù)邏輯有一系列ChannelHandler處理屎蜓。
    netty中分為 inBound 和 outBound, 在channelpipeline 中痘昌, inbound 和outbound channelhandler 處理讀和寫(xiě)。
    可以通過(guò)下面代碼創(chuàng)建:
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("handler1", firstHandler);  
pipeline.addFirst("handler2", new SecondHandler());  
pipeline.addLast("handler3", new ThirdHandler());  

當(dāng)然在netty還有其他幾個(gè)重要成員Channel, ChannelHandlerContext, EventLoop, EventLoopGroup, 這些不在這里闡述炬转, 有興趣的話可以看《netty in action》控汉。

后話

職責(zé)鏈模式能讓模塊結(jié)構(gòu)更加清晰, 節(jié)點(diǎn)與節(jié)點(diǎn)之間的修改影響會(huì)非常小返吻。 但是并不適合所有的場(chǎng)景姑子, 要結(jié)合具體的場(chǎng)景分析。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末测僵,一起剝皮案震驚了整個(gè)濱河市街佑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捍靠,老刑警劉巖沐旨,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異榨婆,居然都是意外死亡磁携,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)良风,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谊迄,“玉大人,你說(shuō)我怎么就攤上這事烟央⊥撑担” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵疑俭,是天一觀的道長(zhǎng)粮呢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)钞艇,這世上最難降的妖魔是什么啄寡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮哩照,結(jié)果婚禮上挺物,老公的妹妹穿的比我還像新娘。我一直安慰自己葡秒,他們只是感情好姻乓,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布嵌溢。 她就那樣靜靜地躺著眯牧,像睡著了一般蹋岩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上学少,一...
    開(kāi)封第一講書(shū)人閱讀 52,713評(píng)論 1 312
  • 那天剪个,我揣著相機(jī)與錄音,去河邊找鬼版确。 笑死扣囊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绒疗。 我是一名探鬼主播侵歇,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吓蘑!你這毒婦竟也來(lái)了惕虑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤磨镶,失蹤者是張志新(化名)和其女友劉穎溃蔫,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體琳猫,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伟叛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脐嫂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片统刮。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖账千,靈堂內(nèi)的尸體忽然破棺而出网沾,到底是詐尸還是另有隱情,我是刑警寧澤蕊爵,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布辉哥,位于F島的核電站,受9級(jí)特大地震影響攒射,放射性物質(zhì)發(fā)生泄漏醋旦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一会放、第九天 我趴在偏房一處隱蔽的房頂上張望饲齐。 院中可真熱鬧,春花似錦咧最、人聲如沸捂人。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)滥搭。三九已至酸纲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瑟匆,已是汗流浹背闽坡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留愁溜,地道東北人疾嗅。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像冕象,于是被迫代替她去往敵國(guó)和親代承。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容