簡體中文 | 繁體中文

大話設計模式-----第44章


天藍色思念之青春篇 重生逆襲之路 撒旦總裁:前妻,我要你 桃花緣 豪門情劫:槓上冷情惡少 異世為僧 異界仙旅 都市修煉研究生 毒女擒夫:王爺莫要逃 穿越千年夢之歡顏 足球之外掛中場 無盡海域 星辰毀滅計 八步道人 你堵了我天堂路 農家傻夫 易中天品三國 殺手穿越:將軍府六小姐 初刻拍案驚奇 駭客無間道
第44章

大B:“擊鼓傳花便是責任鏈模式的應用。在責任鏈模式裡,很多的物件由每一個物件對其下家的引用而聯接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個物件決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個物件最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。”

小A:“哇!這就是責任鏈模式啊?聽起來好像有點複雜喔。”

大B:“其實很簡單的。責任鏈可能是一條直線、一個環鏈甚至一個樹結構的一部分。”

小A:“這樣一說好像很簡單,但聽起來好像很複雜似的。”

小A:“那你剛才說的紅樓夢中擊鼓傳花的故事不是就是符合責任鏈模式嗎?”

大B:“顯然,擊鼓傳花符合責任鏈模式的定義。參加遊戲的人是一個個的具體處理者物件,擊鼓的人便是客戶端物件。花代表酒令,是傳向處理者的請求,每一個參加遊戲的人在接到傳來的花時,可選擇的行為只有兩個:一是將花向下傳;一是執行酒令——喝酒。一個人不能既執行酒令,又向下家傳花;當某一個人執行了酒令之後,遊戲重新開始。擊鼓的人並不知道最終是由哪一個做遊戲的人執行酒令,當然執行酒令的人必然是做遊戲的人們中的一個。”

大B:“單獨考慮擊鼓傳花系統,那麼像賈母、賈赦、賈政、賈寶玉和賈環等傳花者均應當是‘具體傳花者’的物件,而不應當是單獨的類;但是責任鏈模式往往是建立在現有系統的基礎之上的,因此鏈的結構和組成不由責任鏈模式本身決定。”

小A:“喔!是嗎?”

大B:“系統的分析在《紅樓夢》第七十五回裡生動地描述了賈府裡的一場擊鼓傳花遊戲:‘賈母坐下,左垂首賈赦,賈珍,賈璉,賈蓉,右垂首賈政,寶玉,賈環,賈蘭,團團圍坐。賈母便命折一枝桂花來,命一媳婦在屏後擊鼓傳花。若花到誰手中,飲酒一杯。於是先從賈母起,次賈赦,一一接過。鼓聲兩轉,恰恰在賈政手中住了,只得飲了酒。’這場遊戲接著又把花傳到了寶玉和賈赦手裡,接著又傳到了在賈環手裡……如果用一個物件系統描述賈府,那麼賈母、賈赦、賈政、賈寶玉和賈環等等就應當分別由一個個具體類代表,而這場擊鼓傳花遊戲的類圖,按照責任鏈模式。”

大B:換言之,在擊鼓傳花遊戲裡面,有下面的幾種角色:抽象傳花者,或Handler角色、定義出參加遊戲的傳花人要遵守的規則,也就是一個處理請求的介面和對下家的引用;具體傳花者,或ConcreteHandler角色、每一個傳花者都知道下家是誰,要麼執行酒令,要麼把花向下傳。這個角色由賈母、賈赦、賈珍、賈璉、賈蓉、賈政、寶玉、賈環、賈蘭等扮演。擊鼓人,或Client角色、即行酒令的擊鼓之人。《紅樓夢》沒有給出此人的具體姓名,只是說由一媳大B:可以看出,擊鼓傳花遊戲滿足責任鏈模式的定義,是純的責任鏈模式的例子。擊鼓傳花的類圖完全符合責任鏈模式的定義的類圖給出了這些類的具體介面設計。不難看出,DrumBeater(擊鼓者)、Player(傳花者)、JiaMu(賈母)、JiaShe(賈赦)、JiaZheng(賈政)、JiaBaoYu(寶玉)、JiaHuan(賈環)等組成這個系統。

下面是客戶端類DrumBeater的原始碼:

publicclassDrumBeater

{

privatestaticPlayerplayer;

staticpublicvoidmain(String[]args)

{

player=newJiaMu(newJiaShe(newJiaZheng(newJiaBaoYu(newJiaHuan(null)))));

player.handle(4);

}

}

程式碼清單1、DrumBeater的原始碼。

abstractclassPlayer

{

abstractpublicvoidhandle(inti);

privatePlayersuccessor;

publicPlayer(){successor=null;

}

protectedvoidsetSuccessor(PlayeraSuccessor)

{

successor=aSuccessor;

}

publicvoidnext(intindex)

{

if(successor!=null)

{

successor.handle(index);

}

else

{

System.out.println(“rogramterminated.”);

}

}

}

程式碼清單2、抽象傳花者Play類的原始碼。

大B:“抽象類Player給出了兩個方法的實現,以格式setSuccessor(),另一個是next()。前者用來設定一個傳花者物件的下家,後者用來將酒令傳給下家。Player類給出了一個抽象方法handle(),代表執行酒令。”

下面的這些具體傳花者類將給出handle()方法的實現。

classJiaMuextendsPlayer

{

publicJiaMu(PlayeraSuccessor)

{

this.setSuccessor(aSuccessor);

}

publicvoidhandle(inti)

{

if(i……1)

{

System.out.println(“JiaMugottadrink!”);

}

else

{

System.out.println(“JiaMupassed!”);next(i);

}

}

}

程式碼清單3、代表賈母的JiaMu類的原始碼。

classJiaSheextendsPlayer

{

publicJiaShe(PlayeraSuccessor)

{

this.setSuccessor(aSuccessor);

}

publicvoidhandle(inti)

{

if(i……2)

{

System.out.println(“JiaShegottadrink!”);

}

else

{

System.out.println(“JiaShepassed!”);

next(i);

}

}

}

程式碼清單4、代表賈赦的JiaShe類的原始碼。

classJiaZhengextendsPlayer

{

publicJiaZheng(PlayeraSuccessor)

{

this.setSuccessor(aSuccessor);

}

publicvoidhandle(inti)

{

if(i……3)

{

System.out.println(“JiaZhenggottadrink!”);

}

else

{

System.out.println(“JiaZhengpassed!”);

next(i);

}

}

}

程式碼清單5、代表賈政的JiaZheng類的原始碼。

classJiaBaoYuextendsPlayer

{

publicJiaBaoYu(PlayeraSuccessor)

{

this.setSuccessor(aSuccessor);

}

publicvoidhandle(inti)

{

if(i……4)

{

System.out.println(“JiaBaoYugottadrink!”);

}

else

{

System.out.println(“JiaBaoYupassed!”);

next(i);

}

}

}

程式碼清單6、代表賈寶玉的JiaBaoYu類的原始碼。

classJiaHuanextendsPlayer

{

publicJiaHuan(PlayeraSuccessor)

{

this.setSuccessor(aSuccessor);

}

publicvoidhandle(inti)

{

if(i……5)

{

System.out.println(“JiaHuangottadrink!”);

}

else

{

System.out.println(“JiaHuanpassed!”);

next(i);

}

}

}

程式碼清單7、代表賈環的JiaHuan類的原始碼。

大B:“可以看出,DrumBeater設定了責任鏈的成員和他們的順序:責任鏈由賈母開始到賈環,週而復始。JiaMu類、JiaShe類、JiaZheng類、JiaBaoYu類與JiaHuan類均是抽象傳花者Player類的子類。實現的DrumBeater類在把請求傳給賈母時,實際上指定了由4號傳花者處理酒令。雖然DrumBeater並不知道哪一個傳花者類持有號碼4,但是這個號碼在本系統一開始就寫死的。這當然並不符合擊鼓傳花遊戲的精神,因為這個遊戲實際上要求有兩個同時進行的過程:擊鼓過程和傳花過程。擊鼓應當是定時停止的,當擊鼓停止時,執行酒令者就確定了。”

推薦小說