C#面向對象設計模式縱橫談 第20講:Chain Of Responsibility 職責鏈模式

人文精神  >>>  技術的天空 溫和的思緒

2006.8.18 李建忠

請求的發送者與接受者

某些對象請求的接受者可能多種多樣,變化無常……

image

 

動機(Motivation)

在軟件構建過程中,一個請求可能被多個對象處理,但是每個請求在運行時只能有一個接受者,如果顯示指定,將必不可少地帶來請求發送者與接受者的緊耦合。

如何使請求的發送者不需要指定具體的接受者?讓請求的接受者自己在運行時決定來處理請求,從而使兩者解耦。

 

意圖(Intent)

使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈,并沿著這條鏈傳遞請求,直到有一個對象處理它為止。

——《設計模式》GoF

 

例說Chain of Responsibility應用

請求的接收者

image

請求者

image

image

這樣做請求的發送者和接收者之間耦合得太多。例如list的結構需要請求的發送者來關心和維護。我們希望能把list的維護讓請求的發送者忘掉,交給請求的接收者去管理。

 

改進的代碼

image

Next屬性相當于鏈表的next指針,默認的行為都是往后繼者去傳遞請求

image

能處理的話自己處理,自己不能處理就交給后繼者處理。

請求發送者

image

這樣就讓請求的接收者自己來負責判斷和處理請求,職責剝離交給了請求的接收者,實現發送者和接收者之間徹底解耦。

客戶程序

image

Sender徹底忘掉了以后有多少個Handler,它只需要知道把請求交給一個對象處理就可以了。

 

結構(Structure)

image

successor是后繼者指針,指向自己,Handler里面本身包含了指向自己的指針,把一個鏈表結構藏在內部,達到解耦。

image

Chain of Responsibility模式最重要的是把責任封裝,把本身應該是請求對象和接收者對象應該耦合的地方剝離,把責任交給接收者對象。我們也可以使多個接收者處理同一個請求。

 

Chain of Responsibility模式的幾個要點

Chain of Responsibility模式的應用場合在于“一個請求可能有多個接受者,但是最后真正的接受者只有一個”,只有這時候請求發送者與接受者的耦合才有可能出現“變化脆弱”的癥狀,職責鏈的目的就是將二者解耦,從而更好地應對變化。

應用了Chain of Responsibility模式后,對象的職責分派將更具靈活性。我們可以在運行時動態添加/修改請求的處理職責。

當我們要新增一個DHandler處理請求,就不需再改原來的代碼了,遵從了開放封閉原則。這樣我們的程序就更賦予變化,更有變化的抵抗力。Handler類本身繼承自BaseHandler類型,又包含了一個BaseHandler類型的對象,這點類似Decorator模式。image

如果請求傳遞到職責鏈的末尾仍得不到處理,應該有一個合理的缺省機制。這也是每一個接受對象的責任,而不是發出請求的對象的責任。

這種模式在處理UI的消息時很常用,但實際上Windows消息循環還是硬編碼的結構。因為效率上的考慮,Windows消息循環是哪個對象有一個請求,則直接到達處理函數的地址。如果鏈條上的對象多了,而真正處理的函數在鏈條后部分,效率會很低下。因此我們在使用這種模式的時候更適合業務流程,即對性能要求不是特別高的情況更加常用。

2010.10.21


MSDN 網絡廣播 李建忠 2013-08-22 08:52:11

[新一篇] C#面向對象設計模式縱橫談 第21講:Memento 備忘錄模式

[舊一篇] C#面向對象設計模式縱橫談 第19講:Observer 觀察者模式
回頂部
寫評論


評論集


暫無評論。

稱謂:

内容:

驗證:


返回列表