代碼執行結果如下圖:
代碼說明
l AccountSystem是一個中介者角色,它負責各個同事類之間的交互。要使同事對象參與它的管理,就需要在內部維護一個同事對象的列表。
l 我們看到,AccountSystem的注冊、充值和消費方法會遍歷相關的同事對象並且調用它們的專有方法進行操作。在全部操作完成之後,它才會更新自己的賬戶。
l GameSystem是一個抽象同事。充值和消費方法都有兩種。一種是給外部調用的充值和消費方法,一種是給外部調用的,另外一種是給AccountSystem調用的。在對外的方法中,GameSystem僅僅是把這個請求轉發給中介者,它自己不做實質性的操作,而在xxxSelf()方法中才做真正的充值、消費操作。
l GameArea1和GameArea2是具體同事,調用父類構造方法來和中介者關聯。
l 中介者模式的特點就是同事自己意識到它需要和一個中介者關聯,而在實際的操作過程中,它們只是負責和中介者通訊並且接受中介者的請求,而不再和其它同事發生直接的關聯。
何時采用
如果一組接口相對穩定(如果GameArea1和GameArea2的充值方法定義不一樣,那麼AccountSystem就有點暈眩了)的對象之間的依賴關系錯綜復雜,依賴關系難以維護,或者會發生變動可以考慮引入中介者模式。
實現要點
l 在C#中可以適用delegate關聯中介者和各同事之間的交互行為,這樣各同事就不需要直接和中介者進行耦合。
l 中介者模式和觀察者模式的區別是,前者應用於多對多雜亂交互行為的統籌處理,後者應用於一(多)對多關系的靈活定制。對於本例來說,集中處理後還需要分散處理,那麼後半階段的處理過程可以應用觀察者模式。對於前一節的例子來說,如果有多個主體角色和多個觀察者進行多對多通訊的話,也可以應用中介者模式來統籌這個多對多的過程(大家可以自己嘗試修改前一節的實例來應用中介者模式)。
l 中介者模式和門面模式的區別是,前者的各同事類需要依靠中介者進行雙向通訊,應用於子系統之間,而後者的子系統往往不會通過門面去和調用方進行通訊,趨向於單向通訊,應用於子系列和更高層次的系統。本例中就有門面模式和中介者模式的影子。
l 中介者模式往往可以在構架的層次進行應用,有的時候和觀察者模式以及門面模式一起使用,有的時候又會向觀察者模式和門面模式退化。其實在應用模式的過程中不必過多考慮模式的准確定位,如果我們確實從中得以,那麼這個名字就不重要了。
注意事項
l 不是所有的系統都需要應用中介者模式把多對多的關系轉化為多對一對多的。如果各個同事之間本來的關聯就很清晰(沒有交錯關聯),或這種關聯並不復雜,沒有必要應用中介者。
l 在實際的應用過程中,中介者做的控制並不會向本例那樣簡單,它可能包含很多的處理邏輯。如果還伴隨著需求的改變,中介者角色可能會越來越難維護,此時可以考慮對中介者角色或處理行為應用其它的一些設計模式。