中介模式(mediator pattern)是一種“平臺式”或“管家式”委派方式。
中介模式中,中介是各個希望相互交互的參與者的共同且唯一代理,它完成消息的轉發或處理。
現實生活中有集市、股票交易所、婚姻介紹所、房屋中介等形形色色的中介(mediator)組織,它們有效地將參與者(participator)的兩兩交互轉化為參與者與中介的交互。但是,這些中介正好是GoF中介模式的錯誤例子。網上有許多人用QQ為例引入中介模式,顯然沒有從代碼的角度分析,純屬想當然。
這里說一個現實的場景。一場Party,有男生/Boy、女生/Girl參加,每個人都可以與其他對象交互。請問,實現這一場景的代碼有多復雜?只有當你真正寫出代碼時,你會發現10萬個對象的彼此交談,也不過兩個類的代碼要寫。
測試代碼中,每一個Party參與者發起一次對話,對話的對象是隨機的。對話的內容為隨機字符,對話必須持續直到隨機字符為b(bay)才結束。某一次運行結果(”//結束“不是程序的輸出):
B1 To B4:"hi"
B4 To B1:"hi d"
B1 To B4:"hi d d"
B4 To B1:"hi d d a"
B1 To B4:"hi d d a a" //結束
B2 To B3:"hi" //結束
B3 To G2:"hi"//結束
B4 To B1:"hi"//結束
G1 To G2:[hi]
G2 To G1:[hi d]
G1 To G2:[hi d d]
G2 To G1:[hi d d d]
G1 To G2:[hi d d d a]
G2 To G1:[hi d d d a d]
G1 To G2:[hi d d d a d c]
G2 To G1:[hi d d d a d c a]
G1 To G2:[hi d d d a d c a a]
G2 To G1:[hi d d d a d c a a a]
G1 To G2:[hi d d d a d c a a a a]
G2 To G1:[hi d d d a d c a a a a c] //居然聊了這么多 //結束
G2 To B2:[hi]
B2 To G2:"hi c"
G2 To B2:[hi c a]
B2 To G2:"hi c a a"
G2 To B2:[hi c a a a]
B2 To G2:"hi c a a a c"
G2 To B2:[hi c a a a c a]
G3 To G1:[hi]
在討論中介模式時,許多人看到對象的交互呈現網狀結構,幾乎每個對象都需要與其他對象發生相互作用。[GoF]中介者模式:“定義一個中介對象來封裝系列對象之間的交互。中介者使各個對象不需要顯示地相互引用,從而使其耦合性松散,而且可以獨立地改變他們之間的交互”。事實上,上述代碼告訴了一個事實,這里不需要中介模式:
①各對象之間并不需要“顯式”持有彼此的引用。Boy和Girl是Actor的子類,即使Party中出現了Boy和Girl等具體類型,Boy和Girl的類體中依賴Actor即可。②多個類(Boy、Girl)的大量對象的交互,并不一定會導致類之間的過度耦合。Boy和Girl之間就不存在任何耦合。類似的,讓家長、老師等參加Party,只要他們是Actor,彼此之間不存在任何耦合。
所以,上面的例子并不是我們需要中介(這里不是中介模式)的原因。然而,如果有一個對象需要找一個女朋友,他一個個地與每一個Girl對象交互,就顯得非常低效和不現實。此時,他需要一個能夠廣播的“平臺”。平臺式的中介中,不管參與者如何形形色色,中介的作用如同一個公告牌。所以非常容易地聯想到觀察者模式,事實上,作為公告牌的“中介模式”就是觀察者模式。
于是,由于中介者Party現在作為交互平臺,它被所有感興趣的參與者觀察!再次不同于[GoF]中介者模式。[GoF]中,它寫道“將Mediator實現為一個觀察者,各Colleague作為Subject”。而此時,我們的代碼是:Mediator實現為一個Subject,各Colleague作為Observer。
這一“平臺式中介的代碼,網上隨處可見。
[GoF]中介者模式:“定義一個中介對象來封裝系列對象之間的交互。中介者使各個對象不需要顯示地相互引用,從而使其耦合性松散..."
這也給我們帶來一個問題:這里的”對象“是什么東西?
在Java等面向對象的語言中,yqj2065一直強調:類是第一性的。程序員編程針對的都是類而非對象。事實上,[GoF]的中介者模式――“管家式”委派方式中,才體現了一個類(的對象)發生狀態改變,將導致許多其他類(的對象)發生相應的變化。和股票交易所、婚姻介紹所等不同,后者雖然參與者有諸多對象,真正的類不多而且交互簡單。
有人說了:Party中有的男女對上眼了,會一直聊到Party結束;有的男生可以一直聊籃球;有的女生只和女生聊,有的女生只和名字好聽的人聊……你怎么處理這些對象?
還是一句話:我將處理的不是對象而是類――匿名類!你可以用匿名類或λ表達式為客戶留下無限的擴展空間。
總之,股票交易所、婚姻介紹所、聊天室的例子,都不是[GoF]中介者模式。