責任鏈模式在現實中也有很多對應的實例。
比方說,一個公司有A,B,C,D四個項目組,各自相鄰。一天,一個客戶打電話進來,說我們某某項目出了點問題,請幫忙解決。電話是由A項目組的人接的,A項目組的人一聽,說這不是我們負責的項目,我們把它交給B項目組吧。B項目組的人一聽,也說,這也不是我們項目組負責的,我們把它交給C項目組吧。C項目組的人一聽,說,這是我們負責的項目,我們來處理吧。
上面的實例很形象的表現了一個責任鏈模式的處理過程:一個項目或過程裡有多個相似的責任,分別由各自的處理模塊來處理;我們的解決方法就是將這些所有的處理模塊組成一個鏈;然後,當一個責任發生時,將這個責任沿著鏈流轉,如果當前處理模塊不處理該責任,則把該責任流轉到鏈的下一個處理模塊,依此類推,直到該責任找到處理模塊為止。
我們都愛讀《西游記》這部小說,其中有一個情節是"孫悟空大戰二郎神",相信大家都很熟悉。
小說裡是這麼描述的:
"悟空見自己的老窩被破壞了,心裡一慌,變成麻雀想跑,二郎神搖身變成了捉麻雀的鷹,
抖抖翅膀就去啄麻雀;悟空急忙又變成一只大鹚鳥,沖向天空,二郎神急忙變成了一只大海鶴,
鑽進雲裡去撲;悟空一見嗖地一聲飛到水裡,變成一條魚。
二郎神從照妖鏡裡看見了悟空,就變成魚鷹,在水面上等著,悟空見了,
急忙變條水蛇,竄到岸邊,接著又變成花鸨,立在蘆葦上。二郎神見他變的太低賤,也不去理他,
變回原來的樣子,取出彈弓,朝著花鸨就打,把悟空打得站立不穩。"
這是其中的一段二人的變幻大戰,描寫的很精彩。其中,孫悟空分別變幻成"麻雀"、"大鹚鳥"、"魚",企圖躲過二郎神的眼睛,達到逃跑的目的。而二郎神也分別變幻成"鷹"、"大海鶴"、"魚鷹"來和孫悟空爭鋒相對。
從上面的分析,如果把二郎神對付孫悟空當做一個過程,那麼孫悟空的三個變幻就是三種不同的職責,而二郎神也通過三個不同的處理模塊來對付它們。
那麼,我們就可以通過責任鏈模式來模擬二郎神和孫悟空的這段變幻大戰了。
首先,二郎神的第一個處理模塊是"鷹":
class Hawk {
def next
def Hawk(next)
{
this.next = next
}
def fight(wukong)
{
if(wukong == 'sparrow')
{
println 'hawk eat sparrow!'
}
else
{
this.next.fight(wukong)
}
}
}
在這個"Hawk"類中,只有一個屬性是"next",指向它的下一個處理模塊。當這個類初始化的時候確定它的下一個處理模塊是什麼。
然後,我們看它的"fight"方法,有一個傳入參數"wukong",代表的是孫悟空的當前變幻,如果它的當前變幻是"麻雀"的話,就被"Hawk"處理;如果不是的話,"Hawk"類就會傳給下一個處理模塊來處理。
當然,二郎神的第二個處理模塊"大海鶴"的功能也跟第一處理模塊相似:
class Crane {
def next
def Crane(next)
{
this.next = next
}
def fight(wukong)
{
if(wukong == 'cormorant')
{
println 'crane eat cormorant!'
}
else
{
this.next.fight(wukong)
}
}
}
可以看到,功能跟"Hawk"類一樣,在這裡我們就不多說了。同樣的還有一個:
class Osprey {
def next
def Osprey(next)
{
this.next = next
}
def fight(wukong)
{
if(wukong == 'fish')
{
println 'osprey eat fish'
}
else
{
this.next.fight(wukong)
}
}
}
這個類也沒有什麼可說的,但是,在責任鏈模式中,還有一個類是必須的,這就是默認的處理模塊,它的作用是處理當這個責任鏈流轉結束的時候,仍然沒有找到適合的處理模塊的話,就交給默認的處理模塊來處理。它的作用實際上是使得這個責任鏈能夠正常流轉處理結束。
在這裡,我們的默認處理模塊是判給孫悟空贏,如下:
class Other {
def fight()
{
println 'wukong win!'
}
}
現在,整個責任鏈宣告完成,我們需要寫一個客戶端代碼來測試它。
def wukong = 'fish'
def erlangshen = new Hawk(new Osprey(new Crane(new Other())))
erlangshen.fight(wukong)
在我們的客戶端代碼中,孫悟空的變幻是一條"魚":
def wukong = 'fish'
而二郎神則有一個變幻的責任鏈:
def erlangshen = new Hawk(new Osprey(new Crane(new Other())))
下面二郎神就要大戰孫悟空了:
erlangshen.fight(wukong)
它的運行結果為:
osprey eat fish