餐馆的故事-浅析职责链模式
我們?cè)诓宛^吃飯的時(shí)候,一般都是在拿到菜單后,選擇喜歡的菜,然后通知服務(wù)員。服務(wù)員會(huì)將我們的定單交給大廚,大廚可能會(huì)親自去做這道菜,也可能安排給小廚來(lái)做,總之,我們不用擔(dān)心他們沒(méi)有人做菜,即使有時(shí)候等的時(shí)間長(zhǎng)點(diǎn)。
下面我們來(lái)分析一下。首先,對(duì)于我們這些點(diǎn)菜的人來(lái)說(shuō),我們一般不了解這些廚師,我們沒(méi)法找到某個(gè)具體的廚師讓他去做,所以只好把請(qǐng)求交給服務(wù)員;然后,對(duì)于餐館的服務(wù)員、大廚、小廚來(lái)說(shuō),他們都可以接受并處理這個(gè)請(qǐng)求,但很明顯,他們有分工,不會(huì)一人去做所有的菜。
簡(jiǎn)單地說(shuō),顧客發(fā)送請(qǐng)求(點(diǎn)菜),餐館的人接受請(qǐng)求(拿到定單),有多個(gè)人可以處理該請(qǐng)求(做菜),或者說(shuō)履行職責(zé),但最后只有一人處理該請(qǐng)求。如下圖所示:
這當(dāng)中就包含了職責(zé)鏈模式(Chain Of Responsibility,簡(jiǎn)稱CoR)。
我們來(lái)看看Gof中CoR的描述:
意圖
使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞請(qǐng)求,直到有一個(gè)對(duì)象處理它為止。
從第一個(gè)對(duì)象開(kāi)始,鏈中收到請(qǐng)求的對(duì)象要么親自處理它,要么轉(zhuǎn)發(fā)給鏈中的下一個(gè)候選者,請(qǐng)求發(fā)送者不確定到底哪個(gè)對(duì)象會(huì)處理它,——我們稱該請(qǐng)求有一個(gè)隱式的接受者(implicit receiver)。
在餐館的例子中,顧客是請(qǐng)求的發(fā)送者,接受者則是服務(wù)員、大廚、小廚,他們構(gòu)成了一條職責(zé)鏈,他們當(dāng)中會(huì)一個(gè)人來(lái)處理請(qǐng)求。
好了,菜終于上來(lái)了,先把它吃掉吧...
現(xiàn)在走出餐館,我們來(lái)看看在一般場(chǎng)景下,CoR的類(lèi)圖是:
參與者
Handler(如Employee)
——定義一個(gè)處理請(qǐng)求的接口;
ConcreteHandler(如Server和Chef)
——處理它負(fù)責(zé)的請(qǐng)求;
——可訪問(wèn)它的后繼者(Successor);
——如果可處理該請(qǐng)求,處理之;否則轉(zhuǎn)發(fā)給后繼者;
Client
——向職責(zé)鏈提交請(qǐng)求。
適用性
1、有多個(gè)的對(duì)象可以處理一個(gè)請(qǐng)求,而具體的處理者在運(yùn)行時(shí)自動(dòng)確定;
2、希望在對(duì)接受者不了解的情況下,向多個(gè)對(duì)象的一個(gè)提交請(qǐng)求;
3、處理請(qǐng)求的對(duì)象集合需要?jiǎng)討B(tài)指定。
示例代碼:
using System; ? namespace ChainOfPatterns { class Program { static void Main(string[] args) { // 餐館工作人員 Server server = new Server("anders"); Chef chef = new Chef("dudu"); AssistantChef ac = new AssistantChef("bill"); server.SetSuccessor(chef); chef.SetSuccessor(ac); ? Customer customer = new Customer(); // 點(diǎn)第一道菜 customer.OrderName = "酸辣土豆絲"; server.HandleRequest(customer); ? // 點(diǎn)第二道菜 customer.OrderName = "農(nóng)家小炒肉"; server.HandleRequest(customer); ? Console.ReadLine(); } } ? public class Customer { private string orderName; ? public string OrderName { get { return orderName; } set { orderName = value; } } } ? public abstract class Employee { protected string name; protected Employee successor; ? public Employee(string name) { this.name = name; } ? public void SetSuccessor(Employee successor) { this.successor = successor; } ? public virtual void HandleRequest(Customer customer) { if (successor != null) { successor.HandleRequest(customer); } } } ? /// <summary> /// 服務(wù)員不用炒菜,所以直接轉(zhuǎn)發(fā)給后繼者。 /// </summary> public class Server : Employee { public Server(string name) : base(name) { } } ? public class Chef : Employee { public Chef(string name) : base(name) { } ? public override void HandleRequest(Customer customer) { if (customer.OrderName == "農(nóng)家小炒肉") { Console.WriteLine("{0}做的{1}", name, customer.OrderName); } else { base.HandleRequest(customer); } } } ? public class AssistantChef : Employee { public AssistantChef(string name) : base(name) { } ? public override void HandleRequest(Customer customer) { if (customer.OrderName == "酸辣土豆絲") { Console.WriteLine("{0}做的{1}", name, customer.OrderName); } else { base.HandleRequest(customer); } } } }注意:
如果我們運(yùn)氣很差,點(diǎn)了一個(gè)沒(méi)有存貨的菜,那么不管是服務(wù)員還是大廚、小廚都沒(méi)法處理了。也就是說(shuō),對(duì)于一個(gè)請(qǐng)求,可能沒(méi)有任何接受者會(huì)處理它。
問(wèn)題:
我還想到一個(gè)問(wèn)題,如果一道菜很復(fù)雜,需要大廚和小廚一起做,該怎么辦呢?望各路高手指點(diǎn)迷津 :)
其它的例子:
瀏覽器事件模型
假設(shè)我們的HTML頁(yè)面上有一個(gè)<div />,它又包含了一個(gè)<input />按鈕,對(duì)于按鈕的click事件來(lái)說(shuō),在IE中它的觸發(fā)順序?yàn)閺淖钐囟ǖ氖录繕?biāo)(button)道最不特定的事件目標(biāo)(document對(duì)象)。input,div,body到document,它們也構(gòu)成了一條職責(zé)鏈。
擊鼓傳花
擊鼓傳花是一種熱鬧而又緊張的飲酒游戲。在酒宴上賓客依次坐定位置,由一人擊鼓,擊鼓的地方與傳花的地方是分開(kāi)的,以示公正。開(kāi)始擊鼓時(shí),花束就開(kāi)始依次傳遞,鼓聲一落,如果花束在某人手中,則該人就得飲酒。
看起來(lái),酒宴上的賓客構(gòu)成了一條鏈。但我認(rèn)為這是CoR的一個(gè)反面例子。對(duì)于每一輪具體的游戲來(lái)說(shuō),這些賓客唯一能做的事情就是將花束傳遞(轉(zhuǎn)發(fā)給后繼者),沒(méi)有誰(shuí)能夠主動(dòng)停下來(lái),而能夠處理請(qǐng)求的人(擊鼓者)到底是誰(shuí)的后繼者呢?這個(gè)并不確定,職責(zé)鏈如何構(gòu)建呢?
另外,建議看一看下面兩篇文章中高手的論述:職責(zé)鏈模式在開(kāi)發(fā)中的應(yīng)用,手拉手就是職責(zé)鏈嗎?
?
參考:
《設(shè)計(jì)模式-可復(fù)用面向?qū)ο筌浖幕A(chǔ)》 Gof
《UML基礎(chǔ)、案例與應(yīng)用》Joseph Schmuller
http://www.dofactory.com/Patterns/PatternChain.aspx
本文轉(zhuǎn)自一個(gè)程序員的自省博客園博客,原文鏈接:http://www.cnblogs.com/anderslly/archive/2008/02/28/chainOfResponsibility.html,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者。
總結(jié)
以上是生活随笔為你收集整理的餐馆的故事-浅析职责链模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: js渲染模板html,一个javascr
- 下一篇: 肽键肽链内部分的计算机术语大全,生化资料