1. 程式人生 > >設計模式系列之中介者模式(Mediator Pattern)——協調多個物件之間的互動

設計模式系列之中介者模式(Mediator Pattern)——協調多個物件之間的互動

說明:設計模式系列文章是讀`劉偉`所著`《設計模式的藝術之道(軟體開發人員內功修煉之道)》`一書的閱讀筆記。個人感覺這本書講的不錯,有興趣推薦讀一讀。詳細內容也可以看看此書作者的部落格`https://blog.csdn.net/LoveLion/article/details/17517213` ## 模式概述 很多在一線城市漂泊的朋友或多或少都會遇到租房的難題,你是怎樣找到物美價廉的房子的呢,可以在評論區分享經驗哦。相信大多數小夥伴是通過`中介`找房子的,實話說,通過中介,只要說出你的預算以及大致需求(比如`單間帶獨衛`、`朝南大臥室帶陽臺`等),中介會快速提供符合你情況房源。這裡可以看出,`中介者`協調了房東與租客之間錯綜複雜的關係,將一個網狀的關係結構變成一個以中介者為中心的星形結構,讓多對多的關係更容易維護。 未引入中介者,物件之間(這些物件稱為`同事物件`,它們之間通過彼此的相互作用實現系統的行為)的關係圖如下所示: ![物件之間存在複雜關係的網狀結構](https://img2020.cnblogs.com/blog/1546632/202006/1546632-20200625220550529-1223591117.png) 引入中介者可以使物件之間的關係數量急劇減少。在這個星形結構中,物件不再直接與另一個物件聯絡,它通過中介者物件與另一個物件發生相互作用。 ![引入中介者物件的星型結構](https://img2020.cnblogs.com/blog/1546632/202006/1546632-20200625221110744-82013038.png) ### 模式定義 如果在一個系統中物件之間存在多對多的相互關係,我們可以將物件之間的一些互動行為從各個物件中分離出來,並集中封裝在一箇中介者物件中,並由該中介者進行統一協調,這樣物件之間多對多的複雜關係就轉化為相對簡單的一對多關係。通過引入中介者來簡化物件之間的複雜互動,中介者模式是“迪米特法則”的一個典型應用。 > 中介者模式(`Mediator Pattern`):用一箇中介物件(中介者)來封裝一系列的物件互動,中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。中介者模式又稱為調停者模式,它是一種物件行為型模式。 ### 模式結構圖 在中介者模式中,引入了用於協調其他物件/類之間相互呼叫的中介者類,為了讓系統具有更好的靈活性和可擴充套件性,通常還提供了抽象中介者,其結構圖如下圖所示: ![中介者模式結構圖](https://img2020.cnblogs.com/blog/1546632/202006/1546632-20200625221449414-1079230543.png) 在中介者模式結構圖中包含如下幾個角色: - Mediator(抽象中介者):它定義一個介面,該介面用於與各同事物件之間進行通訊。 - ConcreteMediator(具體中介者):它是抽象中介者的子類,通過協調各個同事物件來實現協作行為,它維持了對各個同事物件的引用。 - Colleague(抽象同事類):它定義各個同事類公有的方法,並聲明瞭一些抽象方法來供子類實現,同時它維持了一個對抽象中介者類的引用,其子類可以通過該引用來與中介者通訊。 - ConcreteColleague(具體同事類):它是抽象同事類的子類;每一個同事物件在需要和其他同事物件通訊時,先與中介者通訊,通過中介者來間接完成與其他同事類的通訊;在具體同事類中實現了在抽象同事類中宣告的抽象方法。 中介者模式的核心在於中介者類的引入,在中介者模式中,中介者類承擔了兩方面的職責: (1) 中轉作用(結構性):通過中介者提供的中轉作用,各個同事物件就不再需要顯式引用其他同事,當需要和其他同事進行通訊時,可通過中介者來實現間接呼叫。該中轉作用屬於中介者在結構上的支援。 (2) 協調作用(行為性):中介者可以更進一步的對同事之間的關係進行封裝,同事可以一致的和中介者進行互動,而不需要指明中介者需要具體怎麼做,中介者根據封裝在自身內部的協調邏輯,對同事的請求進行進一步處理,將同事成員之間的關係行為進行分離和封裝。該協調作用屬於中介者在行為上的支援。 ### 模式虛擬碼 典型的抽象中介者類、抽象同事類典型程式碼如下: ```java // 抽象中介者類 public abstract class Mediator { // 用於儲存同事物件 protected List colleagues = new ArrayList<>(); // 註冊方法,用於增加同事物件 public void register(Colleague colleague) { colleagues.add(colleague); } // 宣告抽象的業務方法 public abstract void operation(); } // 抽象同事類 public abstract class Colleague { // 維持一個抽象中介者的引用 protected Mediator mediator; public Colleague(Mediator mediator) { this.mediator = mediator; } // 宣告自身方法,處理自己的行為 public abstract void method1(); // 定義依賴方法,與中介者進行通訊 public void method2() { mediator.operation(); } } ``` 具體中介者類、具體同事類實現這些抽象方法,典型程式碼如下: ```java // 具體同事類 public class ConcreteColleague extends Colleague { public ConcreteColleague(Mediator mediator) { super(mediator); } @Override public void method1() { // 實現自身方法 } } // 具體中介者類 public class ConcreteMediator extends Mediator { @Override public void operation() { // 通過呼叫同事類的方法,並增加其他業務邏輯來控制同事之間的互動 } } ``` ## 模式應用 待完善... ## 模式總結 中介者模式將一個網狀的系統結構變成一個以中介者物件為中心的星形結構,在這個星型結構中,使用中介者物件與其他物件的一對多關係來取代原有物件之間的多對多關係。中介者模式在`事件驅動`類軟體中應用較為廣泛,特別是基於`GUI`(`Graphical User Interface`,圖形使用者介面)的應用軟體,此外,在類與類之間存在錯綜複雜的關聯關係的系統中,中介者模式都能得到較好的應用。 ### 主要優點 (1) 中介者模式簡化了物件之間的互動,它用中介者和同事的一對多互動代替了原來同事之間的多對多互動,一對多關係更容易理解、維護和擴充套件,將原本難以理解的網狀結構轉換成相對簡單的星型結構。 (2) 中介者模式可將各同事物件解耦。中介者有利於各同事之間的鬆耦合,我們可以獨立的改變和複用每一個同事和中介者,增加新的中介者和新的同事類都比較方便,更好地符合“開閉原則”。 (3) 可以減少子類生成,中介者將原本分佈於多個物件間的行為集中在一起,改變這些行為只需生成新的中介者子類即可,這使各個同事類可被重用,無須對同事類進行擴充套件。 ### 主要缺點 中介者類中包含了大量同事之間的互動細節,可能會導致具體中介者類非常複雜,使得系統難以維護。 ### 適用場景 (1) 系統中物件之間存在複雜的引用關係,系統結構混亂且難以理解。 (2) 一個物件由於引用了其他很多物件並且直接和這些物件通訊,導致難以複用該物件。 (3) 想通過一箇中間類來封裝多個類中的行為,而又不想生成太多的子類。可以通過引入中介者類來實現,在中介者中定義物件互動的公共行為,如果需要改變行為則可以增加新的具體中介