設計模式之中介者模式詳解(Mediator Pattern)

在現實生活中,常常會出現好多對象之間存在複雜的交互關係,這種交互關係常常是“網狀結構”,它要求每個對象都必須知道它需要交互的對象。例如,每個人必須記住他(她)所有朋友的電話;而且,朋友中如果有人的電話修改了,他(她)必須告訴其他所有的朋友修改,這叫作“牽一髮而動全身”,非常複雜。

如果把這種“網狀結構”改爲“星形結構”的話,將大大降低它們之間的“耦合性”,這時只要找一個“中介者”就可以了。如前面所說的“每個人必須記住所有朋友電話”的問題,只要在網上建立一個每個朋友都可以訪問的“通信錄”就解決了。這樣的例子還有很多,例如,你剛剛參力口工作想租房,可以找“房屋中介”;或者,自己剛剛到一個陌生城市找工作,可以找“人才交流中心”幫忙。

在軟件的開發過程中,這樣的例子也很多,例如,在 MVC 框架中,控制器(C)就是模型(M)和視圖(V)的中介者;還有大家常用的 QQ 聊天程序的“中介者”是 QQ 服務器。所有這些,都可以採用“中介者模式”來實現,它將大大降低對象之間的耦合性,提高系統的靈活性

認識中介者模式

中介者模式(Mediator Pattern),用一箇中介對象來封裝一系列的對象交互。中介者使各個對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互

中介者模式是一種對象行爲型模式,其主要優點是:

  1. 鬆散耦合、將多個對象之間的聯繫緊耦合封裝到中介對象中,做到松耦合。不會導致一動牽全身。

  2. 將多個對象之間的交互聯繫集中在中介對象中。發送變化僅需修改中介對象即可、提供系統的靈活性、使同事對象獨立而易於複用。

  3. 符合迪米特原則。就是說一個對象應當對其他對象有儘可能少的瞭解。減少各個對象之間的瞭解。

其主要缺點是:
當同事類太多時,中介者的職責將很大,它會變得複雜而龐大,以至於系統難以維護。

原理類圖與角色說明

中介者模式的原理類圖

角色說明

  • 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事對象註冊與轉發同事對象信息的抽象方法。
  • 具體中介者(ConcreteMediator)角色:實現中介者接口,定義一個 List 來管理同事對象,協調各個同事角色之間的交互關係,因此它依賴於同事角色。
  • 抽象同事類(Colleague)角色:定義同事類的接口,保存中介者對象,提供同事對象交互的抽象方法,實現所有相互影響的同事類的公共功能。
  • 具體同事類(Concrete Colleague)角色:是抽象同事類的實現者,當需要與其他同事對象交互時,由中介者對象負責後續的交互。

模式應用場景

  1. 系統中對象間存在較爲複雜引用,導致依賴關係和結構混亂而無法複用的情況。

  2. 想通過一箇中間類來封裝多個類的行爲,但是又不想要太多的子類。

應用實例

下面以房產中介爲實例應用中介者模式:

創建抽象中介者(Mediator):中介接口
//抽象中介者:中介公司
public interface Medium {
    void register(Customer member);//客戶註冊
    void relay(String from,String ad);//轉發
}
創建具體中介者(ConcreteMediator):房產中介
//具體中介者,房產中介公司
public class EstateMedium implements Medium {
    List<Customer> members = new ArrayList<Customer>();

    @Override
    public void register(Customer member) {
        if (!members.contains(member)) {
            members.add(member);
            member.setMedium(this);
        }
    }

    @Override
    public void relay(String from, String ad) {
        for (Customer ob : members) {
            String name = ob.getName();
            //非自己
            if (!name.equals(from)) {
                ob.receive(from,ad);
            }
        }
    }
}
創建抽象同事類(Colleague):客戶
//抽象同事類:客戶
public abstract class Customer {
    protected String name;
    protected Medium medium;
    public Customer(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setMedium(Medium medium) {
        this.medium = medium;
    }

    public abstract void send(String ad);
    public abstract void receive(String from,String ad);
}
創建具體同事類(Concrete Colleague):買方與賣方
//具體同事類:賣方
public class Seller extends Customer {

    public Seller(String name) {
        super(name);
    }
    @Override
    public void send(String ad) {
        System.out.println(getName()+"發送信息: " + ad);
        medium.relay(name,ad);
    }

    @Override
    public void receive(String from, String ad) {
        System.out.println(getName()+"收到來自"+from + "的信息:" + ad);
    }
}
//具體同事類:買方
public class Buyer extends Customer {
    public Buyer(String name) {
        super(name);
    }
    @Override
    public void send(String ad) {
        System.out.println(getName()+"發送信息: " + ad);
        medium.relay(name,ad);
    }

    @Override
    public void receive(String from, String ad) {
        System.out.println(getName()+"收到來自"+from + "的信息:" + ad);
    }
}
客戶端調用測試
public class Client {
    public static void main(String[] args) {
        Medium md=new EstateMedium();    //房產中介
        Customer seller,buyer;
        seller=new Seller("張三(賣方)");
        buyer=new Buyer("李四(買方)");
        md.register(seller); //客戶註冊
        md.register(buyer);
        seller.send("我有一套房子");
        buyer.send("有兩室一廳的嗎?");
        seller.send("有");
    }
}
輸出結果如下
張三(賣方)發送信息: 我有一套房子
李四(買方)收到來自張三(賣方)的信息:我有一套房子
李四(買方)發送信息: 有兩室一廳的嗎?
張三(賣方)收到來自李四(買方)的信息:有兩室一廳的嗎?
張三(賣方)發送信息: 有
李四(買方)收到來自張三(賣方)的信息:有

補充理解

關於租房中介的例子。假如沒有租房中介。這裏有六個房東需要出租房屋,房屋各不相同、各有各的特點、適合不一樣的人租住。

這六個房東之間剛好有點聯繫。然後都在出租房屋。這時租客A來租房,看了一號房東的房子不滿意、但是一號房東覺得可以讓他去看看其他五個朋友的房間。然後開始聯繫他的五個朋友。這樣運行下去好像有是沒有什麼問題的。但是其中二號房東如果房屋不出租或者出租出去了。也就是發生了變化。這是他則需要通知其他五個朋友,告訴他們不用再給他介紹租客了。這裏就造成了中間一個人發生了變化,需要改動其他五個人。

那麼如何可以解決這種情況呢。我們回到現在。把中介加進來、那六個房東都把房屋交給中介處理。租客A看房間一不滿意直接通過中介看房間二。當房間二被出租了。中介也只需要通知房東二號、然後他們簽訂合同。下次還有人看房間就不會再看房間二了。這裏一個出現了變化也就影響改變了一個。並不會影響其他另外五個房東。這個例子可以更好的幫助我們理解中介者模式。我們下面看兩幅圖。

圖一:不採用中介的房東租房模式,多對多的網格。一動牽全身
在這裏插入圖片描述
圖二:採用中介的租房模式,一對多、一個變動不影響其他
在這裏插入圖片描述
顯然可以看出圖二的“星狀結構”更爲簡單明瞭,各個對象不需要顯式地相互引用,從而使其耦合鬆散,任何一個都可以發生獨立改變,也不會影響到其他對象。

參考

中介者模式(詳解版)
通俗易懂設計模式解析——中介者模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章