用一箇中介對象來封裝一系列的對象交互。中介者使得各對象不須要顯式地相互引用,從而使其耦合鬆散,並且能夠獨立的改變它們之間的交互。java
git
編程
spa
設計
Colleague:3d
同事類的定義,一般實現成爲抽象類,主要負責約束同事對象的類型,並實現一些具體同事類之間的公共功能,好比:每一個具體同事類都應該知道中介者對象,也就是具體同事類都會持有中介者對象,就能夠定義到這個類裏面。視頻
ConcreteColleague: 對象
具體的同事類,實現本身的業務,在須要與其它同事通信的時候,就與持有的中介者通訊,中介者會負責與其它的同事交互。blog
若是沒有主板 若是電腦裏面沒有了主板,那麼各個配件之間就必須自行相互交互,以互相傳送數據,理論上說,基本上各個配件相互之間都存在交互數據的可能繼承
有了主板,各個配件的交互徹底經過主板來完成,每一個配件都只須要和主板交互,而主板知道如何和全部的配件打交道,那就簡單多了
這樣一來,不但開發的時候每一個類會複雜,由於要兼顧其它的類,更要命的是每一個類在發生改動的時候,須要通知全部相關的類一塊兒修改,由於接口或者是功能發生了變更,使用它的地方都得變,太可怕了吧!那該如何來簡化這種多個對象之間的交互呢?
案例:
使用電腦來看電影 爲了演示,考慮一個稍微具體點的功能。在平常生活中,咱們常用電腦來看電影,把這個過程描述出來,這裏僅僅考慮正常的狀況,也就是有主板的狀況,簡化後假定會有以下的交互過程:
1:首先是光驅要讀取光盤上的數據,而後告訴主板,它的狀態改變了
2:主板去獲得光驅的數據,把這些數據交給CPU進行分析處理
3:CPU處理完後,把數據分紅了視頻數據和音頻數據,通知主板,它處理完了
4:主板去獲得CPU處理事後的數據,分別把數據交給顯卡和聲卡,去顯示出視頻和發出聲音
固然這是一個持續的、不斷重複的過程,從而造成不間斷的視頻和聲音,具體的運行過程不在討論之列,假設就有如上簡單的交互關係就能夠了。也就是說想看電影,把光盤放入光驅,光驅開始讀盤,就能夠看電影了
使用模式的解決方案
1:中介者模式的功能
中介者的功能很是簡單,就是封裝對象之間的交互。若是一個對象的操做會引發其它相關對象的變化,或者是某個操做須要引發其它對象的後續或連帶操做,而這個對象又不但願本身來處理這些關係,那麼就能夠找中介者,把全部的麻煩扔給它,只在須要的時候通知中介者,其它的就讓中介者去處理就能夠了。
反過來,其它的對象在操做的時候,可能會引發這個對象的變化,也能夠這麼作。最後對象之間就徹底分離了,誰都不直接跟其它對象交互,那麼相互的關係,所有被集中到中介者對象裏面了,全部的對象就只是跟中介者對象進行通訊,相互之間再也不有聯繫。 把全部對象之間的交互都封裝在中介者當中,無形中還獲得另一個好處,就是可以集中的控制這些對象的交互關係,這樣有什麼變化的時候,修改起來就很方便。
2:須要Mediator接口嗎
有沒有使用Mediator接口的必要,取決因而否會提供多個不一樣的中介者實現。若是中介者實現只有一個的話,並且預計中也沒有須要擴展的要求,那麼就能夠不定義Mediator接口,讓各個同事對象直接使用中介者實現對象;若是中介者實現不僅一個,或者預計中有擴展的要求,那麼就須要定義Mediator接口,讓各個同事對象來面向中介者接口編程,而無需關心具體的中介者實現。
3:同事關係
在中介者模式中,要求這些類都要繼承相同的類,也就是說,這些對象從某個角度講是同一個類型,算是兄弟對象。正是這些兄弟對象之間的交互關係很複雜,才產生了把這些交互關係分離出去,單獨作成中介者對象,這樣一來,這些兄弟對象就成了中介者對象眼裏的同事。
4:同事和中介者的關係
中介者對象和同事對象之間是相互依賴的 。
5:如何實現同事和中介者的通訊
一種實現方式是在Mediator接口中定義一個特殊的通知接口,做爲一個通用的方法,讓各個同事類來調用這個方法 。另一種實現方式是能夠採用觀察者模式,把Mediator實現成爲觀察者,而各個同事類實現成爲Subject,這樣同事類發生了改變,會通知Mediator。Mediator在接到通知事後,會與相應的同事對象進行交互。
6:中介者模式的調用順序示意圖
標準的中介者模式在實際使用中的困難
1:是否有必要爲同事對象定義一個公共的父類?
你們都知道,Java是單繼承的,爲了使用中介者模式,就讓這些同事對象繼承一個父類,這是很很差的;再說了,這個父類目前也沒有什麼特別的公共功能,也就是說繼承它也得不到多少好處。 在實際開發中,不少相互交互的對象自己是沒有公共父類的,強行加上一個父類,會讓這些對象實現起來特別彆扭。
2:同事類有必要持有中介者對象嗎?
同事類須要知道中介者對象,以便當它們發生改變的時候,可以通知中介者對象,可是否須要做爲屬性,並經過構造方法傳入,這麼強的依賴關係呢? 也能夠有簡單的方式去通知中介對象,好比把中介對象作成單例,直接在同事類的方法裏面去調用中介者對象。
3:是否須要中介者接口?
在實際開發中,很常見的狀況是不須要中介者接口的,並且中介者對象也不須要建立不少個實例,由於中介者是用來封裝和處理同事對象的關係的,它通常是沒有狀態須要維護的,所以中介者一般能夠實現成單例。
4:中介者對象是否須要持有全部的同事?
雖然說中介者對象須要知道全部的同事類,這樣中介者才能與它們交互。可是是否須要作爲屬性這麼強烈的依賴關係,並且中介者對象在不一樣的關係維護上,可能會須要不一樣的同事對象的實例,所以能夠在中介者處理的方法裏面去建立、或者獲取、或者從參數傳入須要的同事對象。
5:中介者對象只是提供一個公共的方法,來接受同事對象的通知嗎?
從示例就能夠看出來,在公共方法裏,仍是要去區分究竟是誰調過來,這仍是簡單的,尚未去區分究竟是什麼樣的業務觸發調用過來的,由於不一樣的業務,引發的與其它對象的交互是不同的。 所以在實際開發中,一般會提供具體的業務通知方法,這樣就不用再去判斷究竟是什麼對象,具體是什麼業務了。
基於上面的考慮,在實際應用開發中,常常會簡化中介者模式,來使開發變得簡單,好比有以下的簡化:
1:一般會去掉同事對象的父類,這樣可讓任意的對象,只要須要相互交互,就能夠成爲同事;
2:還有一般不定義Mediator接口,把具體的中介者對象實現成爲單例;
3:另一點就是同事對象再也不持有中介者,而是在須要的時候直接獲取中介者對象並調用;中介者也再也不持有同事對象,而是在具體處理方法裏面去建立、或者獲取、或者從參數傳入須要的同事對象。 把這樣通過簡化、變形使用的狀況稱爲廣義中介者。
廣義中介者示例——部門與人員
1:部門和人員的關係 : 是 多對多的
2:問題的出現想一想部門和人員的功能交互,舉幾個常見的功能:
(1)部門被撤銷(2)部門之間進行合併(3)人員離職(4)人員從一個部門調職到另一個部門
想一想要實現這些功能,按照前面的設計,該怎麼作呢?
(1)系統運行期間,部門被撤銷了,就意味着這個部門不存在了,但是原來這個部門下全部的人員,每一個人員的所屬部門中都有這個部門呢,那麼就須要先通知全部的人員,把這個部門從它們的所屬部門中去掉,而後才能夠清除這個部門。
(2)部門合併,是合併成一個新的部門呢,仍是把一個部門併入到另外一個部門?若是是合併成一個新的部門,那麼須要把原有的兩個部門撤銷,而後再新增一個部門;若是是把一個部門合併到另外一個部門裏面,那就是撤銷掉一個部門,而後把這個部門下的人員移動到這個部門。無論是那種狀況,都面臨着須要通知相應的人員進行更改這樣的問題
(3)人員離職了,反過來就須要通知他所屬於的部門,從部門的擁有人員的記錄中去除掉這我的員。
(4)人員調職,一樣須要通知相關的部門,先從原來的部門中去除掉,而後再到新的部門中添加上。
看了上述的描述,感受如何?
麻煩的根源在什麼地方呢?仔細想一想,對了,麻煩的根源就在於部門和人員之間的耦合,這樣致使操做人員的時候,須要操做全部相關的部門,而操做部門的時候又須要操做全部相關的人員,使得部門和人員攪和在了一塊兒。
3:中介者來解決
找到了根源就好辦了,採用中介者模式,引入一箇中介者對象來管理部門和人員之間的關係,就能解決這些問題了。 若是採用標準的中介者模式,想一想上面提出的那些問題點吧,就知道實現起來會很彆扭。所以採用廣義的中介者來解決,這樣部門和人員就徹底解耦了,也就是說部門不知道人員,人員也不知道部門,它們徹底分開,它們之間的關係就徹底由中介者對象來管理了。
1:鬆散耦合
適當地使用中介者模式能夠避免同事類之間的過分耦合,使得各同事類之間能夠相對獨立地使用。
2:集中控制交互
使用中介者模式能夠將對象的行爲和協做進行抽象,可以比較靈活的處理對象間的相互做用。
3:多對多變成一對多
使用中介者模式能夠將對象間一對多的關聯轉變爲一對一的關聯,使對象間的關係易於理解和維護。
4:過分集中化
中介者模式的本質是:封裝交互
1:若是一組對象之間的通訊方式比較複雜,致使相互依賴、結構混亂,能夠採用中介者模式,把這些對象相互的交互管理起來,各個對象都只須要和中介者交互,從而使得各個對象鬆散耦合,結構也更清晰易懂
2:若是一個對象引用不少的對象,並直接跟這些對象交互,致使難以複用該對象。能夠採用中介者模式,把這個對象跟其它對象的交互封裝到中介者對象裏面,這個對象就只須要和中介者對象交互就能夠了
在面向對象編程中,一個類必然會與其餘的類發生依賴關係,徹底獨立的類是沒有意義的。一個類同時依賴多個類的狀況也至關廣泛,既然存在這樣的狀況,說明,一對多的依賴關係有它的合理性,適當的使用中介者模式可使本來凌亂的對象關係清晰,可是若是濫用,則可能會帶來反的效果。通常來講,只有對於那種同事類之間是網狀結構的關係,纔會考慮使用中介者模式。能夠將網狀結構變爲星狀結構,使同事類之間的關係變的清晰一些。
中介者模式是一種比較經常使用的模式,也是一種比較容易被濫用的模式。對於大多數的狀況,同事類之間的關係不會複雜到混亂不堪的網狀結構,
代碼地址: https://gitee.com/weixiaotao1992/DesignPatternsForJava