Java設(shè)計(jì)模式的中介者模式
一、引子
中介在現(xiàn)實(shí)生活中并不陌生,滿大街的房屋中介、良莠不齊的出國(guó)中介……。它們的存在是因?yàn)樗鼈兡芙o我們的生活帶來(lái)一些便利:租房、買房用不著各個(gè)小區(qū)里瞎轉(zhuǎn);出國(guó)留學(xué)也不用不知所措。
中介者模式在程序設(shè)計(jì)中也起到了類似的作用。
二、定義與結(jié)構(gòu)
GOF給中介者模式下的定義是:用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互。中介者使各對(duì)象不需要顯式地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。簡(jiǎn)單點(diǎn)來(lái)說(shuō),將原來(lái)兩個(gè)直接引用或者依賴的對(duì)象拆開(kāi),在中間加入一個(gè)“中介”對(duì)象,使得兩頭的對(duì)象分別和“中介”對(duì)象引用或者依賴。
當(dāng)然并不是所有的對(duì)象都需要加入“中介”對(duì)象。如果對(duì)象之間的關(guān)系原本一目了然,中介對(duì)象的加入便是“畫蛇添足”。
來(lái)看下中介者模式的組成部分吧。
1) 抽象中介者(Mediator)角色:抽象中介者角色定義統(tǒng)一的接口用于各同事角色之間的通信。
2) 具體中介者(Concrete Mediator)角色:具體中介者角色通過(guò)協(xié)調(diào)各同事角色實(shí)現(xiàn)協(xié)作行為。為此它要知道并引用各個(gè)同事角色。
3) 同事(Colleague)角色:每一個(gè)同事角色都知道對(duì)應(yīng)的具體中介者角色,而且與其他的同事角色通信的時(shí)候,一定要通過(guò)中介者角色協(xié)作。
來(lái)自《設(shè)計(jì)模式》一書的類圖:

由于中介者的行為與要使用的數(shù)據(jù)與具體業(yè)務(wù)緊密相關(guān),抽象中介者角色提供一個(gè)能方便很多對(duì)象使用的接口是不太現(xiàn)實(shí)的。所以抽象中介者角色往往是不存在的,或者只是一個(gè)標(biāo)示接口。如果有幸能夠提煉出真正帶有行為的抽象中介者角色,我想同事角色對(duì)具體中介者角色的選擇也是策略的一種應(yīng)用。
“恰到好處,過(guò)猶不及”。適合自己系統(tǒng)的便是最好的。
三、進(jìn)一步討論
是否還記得應(yīng)用廣泛的MVC分為哪三層?模型層(Model)、表現(xiàn)層(View)還有控制層(ControlMediator)?刂茖颖闶俏挥诒憩F(xiàn)層與模型層之間的中介者;\統(tǒng)地說(shuō)MVC也算是中介者模式在框架設(shè)計(jì)中的一個(gè)應(yīng)用。
由于中介者模式在定義上比較松散,在結(jié)構(gòu)上和觀察者模式、命令模式十分相像;而應(yīng)用目的又與結(jié)構(gòu)模式“門面模式”有些相似。
在結(jié)構(gòu)上,中介者模式與觀察者模式、命令模式都添加了中間對(duì)象――只是中介者去掉了后兩者在行為上的方向。因此中介者的應(yīng)用可以仿照后兩者的例子去寫。但是觀察者模式、命令模式中的觀察者、命令都是被客戶所知的,具體哪個(gè)觀察者、命令的應(yīng)用都是由客戶來(lái)指定的;而大多中介者角色對(duì)于客戶程序卻是透明的。當(dāng)然造成這種區(qū)別的原因是由于它們要達(dá)到的目的不同。
從目的上看,中介者模式與觀察者模式、命令模式便沒(méi)有了任何關(guān)系,倒是與前面講過(guò)的門面模式有些相似。
但是門面模式是介于客戶程序與子系統(tǒng)之間的,而中介者模式是介于子系統(tǒng)與子系統(tǒng)之間的。這也注定了它們有很大的區(qū)別:門面模式是將原有的復(fù)雜邏輯提取到一個(gè)統(tǒng)一的接口,簡(jiǎn)化客戶對(duì)邏輯的使用。它是被客戶所感知的,而原有的復(fù)雜邏輯則被隱藏了起來(lái)。而中介者模式的加入并沒(méi)有改變客戶原有的使用習(xí)慣,它是隱藏在原有邏輯后面的,使得代碼邏輯更加清晰可用。
前面已經(jīng)陸陸續(xù)續(xù)的將中介者模式的特點(diǎn)寫了出來(lái)。這里再總結(jié)一下。使用中介者模式最大的好處就是將同事角色解耦。這帶來(lái)了一系列的系統(tǒng)結(jié)構(gòu)改善:提高了原有系統(tǒng)的可讀性、簡(jiǎn)化原有系統(tǒng)的通信協(xié)議――將原有的多對(duì)多變?yōu)橐粚?duì)多、提高了代碼的可復(fù)用性……
但是中介者角色集中了太多的責(zé)任,所有有關(guān)的同事對(duì)象都要由它來(lái)控制。這不由得讓我想起了簡(jiǎn)單工廠模式,但是由于中介者模式的特殊性――與業(yè)務(wù)邏輯密切相關(guān),不能采用類似工廠方法模式的解決方法。因此建議在使用中介者模式的時(shí)候注意控制中介者角色的大小。
討論了這么多關(guān)于中介者模式的特點(diǎn)。可以總結(jié)出中介者模式的使用時(shí)機(jī):一組對(duì)象以定義良好但是復(fù)雜的方式進(jìn)行通信,產(chǎn)生了混亂的依賴關(guān)系,也導(dǎo)致對(duì)象難以復(fù)用。
四、總結(jié)
中介者模式很容易在系統(tǒng)中應(yīng)用,也很容易在系統(tǒng)中誤用。當(dāng)系統(tǒng)出現(xiàn)了“多對(duì)多”交互復(fù)雜的對(duì)象群,不要急于使用中介者模式,而要先反思你的系統(tǒng)在設(shè)計(jì)上是不是合理。
下一條:Java程序員的迷失―論“虛擬機(jī)”