1. 程式人生 > 實用技巧 >中介者模式(Mediator Pattern)

中介者模式(Mediator Pattern)

中介者模式(Mediator Pattern)

1.模式動機

  • 在使用者與使用者直接聊天的設計方案中,使用者物件之間存在很強的關聯性,將導致系統出現如下問題:
  • 系統結構複雜:物件之間存在大量的相互關聯和呼叫,若有一個物件發生變化,則需要跟蹤和該物件關聯的其他所有物件,並進行適當處理。
  • 物件可重用性差:由於一個物件和其他物件具有很強的關聯,若沒有其他物件的支援,一個物件很難被另一個系統或模組重用,這些物件表現出來更像一個不可分割的整體,職責較為混亂。
  • 系統擴充套件性低:增加一個新的物件需要在原有相關物件上增加引用,增加新的引用關係也需要調整原有物件,系統耦合度很高,物件操作很不靈活,擴充套件性差。
  • 在面向物件的軟體設計與開發過程中,根據“單一職責原則”,我們應該儘量將物件細化,使其只負責或呈現單一的職責。
  • 對於一個模組,可能由很多物件構成,而且這些物件之間可能存在相互的引用,為了減少物件兩兩之間複雜的引用關係,使之成為一個鬆耦合的系統,我們需要使用中介者模式,這就是中介者模式的模式動機。

2.模式定義

中介者模式(Mediator Pattern)定義:用一箇中介物件來封裝一系列的物件互動,中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。中介者模式又稱為調停者模式,它是一種物件行為型模式。

3.模式結構

中介者模式包含如下角色:

  • Mediator: 抽象中介者
  • ConcreteMediator: 具體中介者
  • Colleague: 抽象同事類
  • ConcreteColleague: 具體同事類

4.時序圖

5.程式碼分析

abstract class AbstractColleague {  
    protected int number;  
  
    public int getNumber() {  
        return number;  
    }  
  
    public void setNumber(int number){  
        this.number = number;  
    }  
    //抽象方法,修改數字時同時修改關聯物件  
    public abstract void setNumber(int number, AbstractColleague coll);  
}
class ColleagueA extends AbstractColleague{  
    public void setNumber(int number, AbstractColleague coll) {  
        this.number = number;  
        coll.setNumber(number*100);  
    }  
}  

class ColleagueB extends AbstractColleague{  
      
    public void setNumber(int number, AbstractColleague coll) {  
        this.number = number;  
        coll.setNumber(number/100);  
    }  
}

abstract class AbstractMediator {  
    protected AbstractColleague A;  
    protected AbstractColleague B;  
      
    public AbstractMediator(AbstractColleague a, AbstractColleague b) {  
        A = a;  
        B = b;  
    }  
  
    public abstract void AaffectB();  
      
    public abstract void BaffectA();  
} 

class Mediator extends AbstractMediator {  
  
    public Mediator(AbstractColleague a, AbstractColleague b) {  
        super(a, b);  
    }  
  
    //處理A對B的影響  
    public void AaffectB() {  
        int number = A.getNumber();  
        B.setNumber(number*100);  
    }  
  
    //處理B對A的影響  
    public void BaffectA() {  
        int number = B.getNumber();  
        A.setNumber(number/100);  
    }  
}
public class Client {  
    public static void main(String[] args){  
        AbstractColleague collA = new ColleagueA();  
        AbstractColleague collB = new ColleagueB();  
          
        AbstractMediator am = new Mediator(collA, collB);  
          
        System.out.println("==========通過設定A影響B==========");  
        collA.setNumber(1000, am);  
        System.out.println("collA的number值為:"+collA.getNumber());  
        System.out.println("collB的number值為A的10倍:"+collB.getNumber());  
  
        System.out.println("==========通過設定B影響A==========");  
        collB.setNumber(1000, am);  
        System.out.println("collB的number值為:"+collB.getNumber());  
        System.out.println("collA的number值為B的0.1倍:"+collA.getNumber());  
          
    }  
}

6.模式分析

中介者模式可以使物件之間的關係數量急劇減少。

中介者承擔兩方面的職責:

  • 中轉作用(結構性):通過中介者提供的中轉作用,各個同事物件就不再需要顯式引用其他同事,當需要和其他同事進行通訊時,通過中介者即可。該中轉作用屬於中介者在結構上的支援。
  • 協調作用(行為性):中介者可以更進一步的對同事之間的關係進行封裝,同事可以一致地和中介者進行互動,而不需要指明中介者需要具體怎麼做,中介者根據封裝在自身內部的協調邏輯,對同事的請求進行進一步處理,將同事成員之間的關係行為進行分離和封裝。該協調作用屬於中介者在行為上的支援。

7.例項

例項:虛擬聊天室

某論壇系統欲增加一個虛擬聊天室,允許論壇會員通過該聊天室進行資訊交流,普通會員(CommonMember)可以給其他會員傳送文字資訊,鑽石會員(DiamondMember)既可以給其他會員傳送文字資訊,還可以傳送圖片資訊。該聊天室可以對不雅字元進行過濾,如“日”等字元;還可以對傳送的圖片大小進行控制。用中介者模式設計該虛擬聊天室。

8.中介者模式的優缺點

優點:

中介者模式的優點

  • 簡化了物件之間的互動。
  • 將各同事解耦。
  • 減少子類生成。
  • 可以簡化各同事類的設計和實現。
缺點:

中介者模式的缺點

  • 在具體中介者類中包含了同事之間的互動細節,可能會導致具體中介者類非常複雜,使得系統難以維護。
適用環境:
  • 系統中物件之間存在複雜的引用關係,產生的相互依賴關係結構混亂且難以理解。
  • 一個物件由於引用了其他很多物件並且直接和這些物件通訊,導致難以複用該物件。
  • 想通過一箇中間類來封裝多個類中的行為,而又不想生成太多的子類。可以通過引入中介者類來實現,在中介者中定義物件。
  • 互動的公共行為,如果需要改變行為則可以增加新的中介者類。

9.模式應用

MVC架構中控制器

Controller 作為一種中介者,它負責控制檢視物件View和模型物件Model之間的互動。如在Struts中,Action就可以作為JSP頁面與業務物件之間的中介者。

10.模式擴充套件

中介者模式與迪米特法則

  • 在中介者模式中,通過創造出一箇中介者物件,將系統中有關的物件所引用的其他物件數目減少到最少,使得一個物件與其同事之間的相互作用被這個物件與中介者物件之間的相互作用所取代。因此,中介者模式就是迪米特法則的一個典型應用。

中介者模式與GUI開發

  • 中介者模式可以方便地應用於圖形介面(GUI)開發中,在比較複雜的介面中可能存在多個介面元件之間的互動關係。
  • 對於這些複雜的互動關係,有時候我們可以引入一箇中介者類,將這些互動的元件作為具體的同事類,將它們之間的引用和控制關係交由中介者負責,在一定程度上簡化系統的互動,這也是中介者模式的常見應用之一。

11.總結

  • 中介者模式用一箇中介物件來封裝一系列的物件互動,中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。中介者模式又稱為調停者模式,它是一種物件行為型模式。
  • 中介者模式包含四個角色:抽象中介者用於定義一個介面,該介面用於與各同事物件之間的通訊;具體中介者是抽象中介者的子類,通過協調各個同事物件來實現協作行為,瞭解並維護它的各個同事物件的引用;抽象同事類定義各同事的公有方法;具體同事類是抽象同事類的子類,每一個同事物件都引用一箇中介者物件;每一個同事物件在需要和其他同事物件通訊時,先與中介者通訊,通過中介者來間接完成與其他同事類的通訊;在具體同事類中實現了在抽象同事類中定義的方法。
  • 通過引入中介者物件,可以將系統的網狀結構變成以中介者為中心的星形結構,中介者承擔了中轉作用和協調作用。中介者類是中介者模式的核心,它對整個系統進行控制和協調,簡化了物件之間的互動,還可以對物件間的互動進行進一步的控制。
  • 中介者模式的主要優點在於簡化了物件之間的互動,將各同事解耦,還可以減少子類生成,對於複雜的物件之間的互動,通過引入中介者,可以簡化各同事類的設計和實現;中介者模式主要缺點在於具體中介者類中包含了同事之間的互動細節,可能會導致具體中介者類非常複雜,使得系統難以維護。
  • 中介者模式適用情況包括:系統中物件之間存在複雜的引用關係,產生的相互依賴關係結構混亂且難以理解;一個物件由於引用了其他很多物件並且直接和這些物件通訊,導致難以複用該物件;想通過一箇中間類來封裝多個類中的行為,而又不想生成太多的子類。