中介者模式(作用,原理、怎麼用、優缺點)

目錄

一、爲什麼要用中介者模式

二、中介者模式中的角色

三、中介者模式怎麼用?

四、中介者模式的優缺點

       優點

       缺點


一、爲什麼要用中介者模式

中介者模式核心在於中介者這個角色,理解上可以參考現實中的中介者,中介就跟中間人一樣,跟橋樑一樣。比方說你到了個陌生的城市,要找工作,要找房子。如果一個人冒冒失失的盲目的找,不僅花費的時間跟精力非常大,即使找到了也不是理想中的。這時候中介就發揮作用了。它會根據你的要求,幫你安排那樣的工作適合你,跟用人方取得聯繫。

代碼的世界裏,如果各個類之間互相依賴,每個類內部引入其他類,當類增多時就會形成網狀依賴關係(下圖左),這時代碼的耦合度就很高;中介者模式可以很好的解耦這種依賴關係,所有類都只和中介者有關聯,形成一種星狀結構(下圖右),通過中介者建立聯繫,而彼此不需要知道對方是誰,彼此獨立,耦合性很低。

                             

說道這你肯定想起了Spring, Spring的一個主要功能就是IOC,各層間、層內不同對象也是不需要事先注入綁定,而是將創建bean的事情全交給Spring處理,Spring負責各方的聯繫。

中介者模式是迪米特原則的經典體現:迪米特法則(Law of Demeter)又叫作最少知識原則(Least Knowledge Principle 簡寫LKP),它要求一個對象應該對其他對象保持最少的瞭解。如果兩個類不必彼此直接通信,那麼這兩個類就不應當發生直接的相互作用。如果其中的一個類需要調用另一個類的某一個方法的話,可以通過第三者轉發這個調用。 

 

二、中介者模式中的角色

中介者模式涉及到的角色有四個:

- 抽象中介者角色:抽象中介者角色定義統一的接口,以及一個或者多個事件方法,用於各同事角色之間的通信。

- 具體中介者角色:實現了抽象中介者所聲明的事件方法,協調各同事類之間的行爲,持有所有同事類對象的引用。

- 抽象同事類角色:定義了抽象同事類,持有抽象中介者對象的引用。

- 具體同事類角色:繼承抽象同事類,實現自己業務,通過中介者跟其他同事類進行通信。

 

三、中介者模式怎麼用?

我們實現下面的一個實例:

比如模擬李雲龍打仗。李雲龍現在要去打鬼子的伏擊搶點彈藥回來,手底下有3個營,鬼子裝備精良,這三個營之間只有互相配合纔有勝算。那李雲龍就是指揮官(中介者),三個營(同事類)完成各自任務,相互間通信配合都通過李雲龍。

抽象同事類:

public interface Colleague {
    void battle();
    void teamWork();
}

 

具體同事類:一營

/**
 * Feng, Ge 2020/3/10 0010 15:02
 */
public class FirstCamp implements Colleague {

    private Mediator mediator;

    public FirstCamp(Mediator mediator) {
        this.mediator = mediator;
        mediator.receive("一營", this);
    }

    @Override
    public void battle() {
        System.out.println("一營要正面進攻了!");
    }

    @Override
    public void teamWork() {
        System.out.println("報告營長,一營任務正面扛不住了,請求李團長派三營接應!");
        mediator.order("三營");
    }
}

 

具體同事類:二營

/**
 * Feng, Ge 2020/3/10 0010 15:02
 */
public class SecondCamp implements Colleague {

    private Mediator mediator;

    public SecondCamp(Mediator mediator) {
        this.mediator = mediator;
        mediator.receive("二營", this);
    }

    @Override
    public void battle() {
        System.out.println("二營要側面進攻了!");
    }

    @Override
    public void teamWork() {
        System.out.println("報告營長,二營側面進攻有些壓力,需要一營正面加強火力掩護!");
        mediator.order("一營");
    }
}

 

具體同事類:三營

/**
 * Feng, Ge 2020/3/10 0010 15:03
 */
public class ThirdCamp implements Colleague {

    private Mediator mediator;

    public ThirdCamp(Mediator mediator) {
        this.mediator = mediator;
        mediator.receive("三營", this);
    }

    @Override
    public void battle() {
        System.out.println("三營在外圍接應!");
    }

    @Override
    public void teamWork() {
        System.out.println("報告營長,三營任務已完成,請指示!");
    }
}

 

抽象中介者:

public interface Mediator {
    // 各營在這裏註冊,接收各營發來的戰況電報
    void receive(String name, Colleague colleague);

    // 下達命令
    void order(String name);
}

 

具體中介者: 李雲龍

/**
 * Feng, Ge 2020/3/10 0010 14:51
 */
public class YunLongLi implements Mediator {

    private Map<String,Colleague> map = new HashMap<String , Colleague>();

    @Override
    public void receive(String name, Colleague colleague) {
        map.put(name, colleague);
    }

    @Override
    public void order(String name) {
        map.get(name).battle();
    }
}

 

測試類:

/**
 * Feng, Ge 2020/3/10 0010 15:49
 */
public class MdiatorTest {
    public static void main(String[] args) {
        Mediator mediator = new YunLongLi();
        FirstCamp firstCamp = new FirstCamp(mediator);
        SecondCamp secondCamp = new SecondCamp(mediator);
        ThirdCamp thirdCamp = new ThirdCamp(mediator);

        firstCamp.battle();
        firstCamp.teamWork();
        System.out.println("====================================");
        secondCamp.battle();
        secondCamp.teamWork();
        System.out.println("====================================");
        thirdCamp.battle();
        thirdCamp.teamWork();
        System.out.println("把老子的意大利炮來出來,轟他孃的小鬼子,秀琴對不住了,開炮!!!!!");
    }
}

結果:

一營要正面進攻了!
報告營長,一營任務正面扛不住了,請求李團長派三營接應!
三營在外圍接應!
====================================
二營要側面進攻了!
報告營長,二營側面進攻有些壓力,需要一營正面加強火力掩護!
一營要正面進攻了!
====================================
三營在外圍接應!
報告營長,三營任務已完成,請指示!
把老子的意大利炮來出來,轟他孃的小鬼子,秀琴對不住了,開炮!!!!!

以上,各營的行動彼此需要支援的時候,例如一營需要三營外圍接應的時候,不是一營長和三營長直接對話,而是通過李雲龍,李雲龍根據name去調用具體的map.get(name).battle()方法。

 

四、中介者模式的優缺點

優點

1)解耦。把同事類原來一對多的依賴變成一對一的依賴,降低同事類的耦合度,同時也符合了迪米特原則。

缺點

1)中介者模式把業務流程和協調都寫在中介者,當同事類越多,中介者的業務就越複雜,造成不好管理的弊端。

2)中介者模式還有一個明顯的缺點,如果要增減同事類,必須得修改抽象中介者角色和具體中介者角色類。

 

中介者模式和代理模式的區別:

代理模式在不改變目標類的基礎上增強目標類功能,目標類是隱藏的,不讓別人知道具體的操作細節,而中介者模式則主要用戶多對象多對多的複雜交互,降低耦合。

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