1. 程式人生 > >設計模式(十四)中介者模式

設計模式(十四)中介者模式

前言

寫了很多篇設計模式的文章,才發現沒有講關於設計模式的分類,那麼這一篇就補上這一內容,順便帶來中介者模式的講解。並與此前講過的代理模式和外觀模式做對比。

1.設計模式的分類

GoF提出的設計模式總共有23種,根據目的準則分類分為三大類:

  • 建立型模式,共五種:單例模式、工廠方法模式、抽象工廠模式、建造者模式、原型模式。
  • 結構型模式,共七種:介面卡模式、裝飾模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
  • 行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代器模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式。

另外隨著設計模式的發展也湧現出很多新的設計模式:它們分別是規格模式、物件池模式、僱工模式、黑板模式和空物件模式等。

2.中介者模式

從前面講到的設計模式的分類中,我們應該得知中介者模式是行為型模式的一種,旨在處理類或物件如何互動及如何分配職責。
中介者模式又叫做調停者模式,名字跟出國留學中介和房產中介是類似的。拿房產中介來說,現在房子買家和房子賣家非常多,如果任由房子買家和房子賣家自由交易,則會導致不同的買家和賣家之間有很多互動,一個買家會和多個賣家進行交涉,同樣的一個賣家也會和多個買家進行交涉。如果在買房的過程中出現糾紛問題,則很難進行解決。就如下圖所示一樣。

可以看出房子買家和賣家進行了很多錯綜複雜的互動,並且買家A和賣家B,買家D和賣家D還產生了糾紛,一看到這個圖我們就覺得的暈,當然比我們暈的還有房子買家和賣家。我們在

設計模式(一)設計六大原則這篇文章講過迪米特原則,這個原則所說的就是要儘量減少物件之間的互動,如果兩個物件之間不必彼此直接通訊,那麼這兩個物件就不應當發生任何直接的相互作用,如果其中的一個物件需要呼叫另一個物件的某一個方法的話,可以通過第三者轉發這個呼叫。迪米特原則同樣適用於本場景,我們可以引入第三者也就是房產中介。它的出現不需要買家和賣家進行直接交涉,而是通過房產中介而進行交涉。並且也不容易出現買賣家之間糾紛,因為有中介者房產中介進行第三方監督。如下圖所示。

圖中的關係清晰了很多。回到我們軟體開發中,我們為了減少物件之間的互動和耦合,符合迪米特原則,那麼就可以使用中介者模式,先來學習下中介者模式的定義。

中介者模式定義

定義:用一箇中介者物件來封裝一系列的物件互動。中介者使得各物件不需要顯式地相互引用,從而使其鬆散耦合,而且可以獨立地改變它們之間的互動。

中介者模式結構圖如下圖所示。


在中介者模式中有如下角色:
- Mediator:抽象中介者角色,定義了同事物件到中介者物件的介面。
- ConcreteMediator:具體中介者角色,它從具體的同事物件接收訊息,向具體同事發出命令。
- Colleague:抽象同事角色,定義了中介者物件介面,它只知道中介者而不知道其他同事物件。
- ConcreteColleague:具體同事角色,每個具體同事類都知道自己在小範圍內的行為,而不知道它在大範圍內的目的。

中介者模式簡單實現

中介者模式可以拿武俠來舉例,江湖中門派眾多,門派之前因為想法不同會有很多的利益衝突,這樣就會帶來無休止的紛爭。為了江湖的安寧,大家推舉出了一個大家都認可的武林盟主來對江湖紛爭進行調停。
前段時間武當派和峨眉派的的弟子被大力金剛指所殺,大力金剛指是少林派的絕學,因為事情重大,而且少林派實力強大,武當派和峨眉派不能夠直接去少林派去問罪,只能上報武林盟主由武林盟主出面進行調停,如下圖所示。

這裡寫圖片描述

抽象中介者角色

首先我們建立抽象中介者類,在這個例子中,它是一個武林聯盟類,如下所示。

public abstract class WulinAlliance {
    public abstract void notice(String message, United united);
}

notice方法用於向門派發送通知,其中United為抽象同事類也就是門派類,接下來我們來建立它。

抽象同事角色
public abstract class United {
    protected WulinAlliance wulinAlliance;
    public United(WulinAlliance wulinAlliance){
        this.wulinAlliance=wulinAlliance;
    }
}

門派類(抽象同事類)會在構造方法中得到武林聯盟類(抽象中介者類)。

具體同事角色

具體同事類包括武當派、峨眉派和少林派,如下所示。

/**
 * 具體同事類(武當)
 */

public class Wudang extends United {
    public Wudang(WulinAlliance wulinAlliance) {
        super(wulinAlliance);
    }
    public void sendAlliance(String message) {
        wulinAlliance.notice(message, this);
    }
    public void getNotice(String message) {
        System.out.println("武當收到訊息:" + message);
    }
}

/**
 * 具體同事類(峨眉派)
 */
public class Emei extends United {
    public Emei(WulinAlliance wulinAlliance) {
        super(wulinAlliance);
    }
    public void sendAlliance(String message) {
        wulinAlliance.notice(message, Emei.this);
    }
    public void getNotice(String message) {
        System.out.println("峨眉收到訊息:" + message);
    }
}

/**
 * 具體同事類(少林派)
 */
public class Shaolin extends United {
    public Shaolin(WulinAlliance wulinAlliance) {
        super(wulinAlliance);
    }
    public void sendAlliance(String message){
        wulinAlliance.notice(message,Shaolin.this);
    }
    public void getNotice(String message){
        System.out.println("少林收到訊息:"+message);
    }
}

武當、峨眉和少林類都有兩個方法,其中getNotice方法是自有方法,對於其他的門派(同事類)和武林聯盟(中介者)沒有依賴,只是用來接收武林盟主的通知。sendAlliance方法則是依賴方法,它必須通過武林盟主才能完成行為。

具體中介者角色

具體中介者類則是武林盟主類,如下所示

public class Champions extends WulinAlliance {
    private Wudang wudang;
    private Shaolin shaolin;
    private Emei emei;
    public void setWudang(Wudang wudang) {
        this.wudang = wudang;
    }
    public void setEmei(Emei emei) {
        this.emei = emei;
    }
    public void setShaolin(Shaolin shaolin) {
        this.shaolin = shaolin;
    }
    @Override
    public void notice(String message, United united) {
        if (united == wudang) {
            shaolin.getNotice(message);
        } else if (united == emei) {
            shaolin.getNotice(message);
        } else if (united == shaolin) {
            wudang.getNotice(message);
            emei.getNotice(message);
        }
    }
}

武林盟主需要了解所有的門派,所以需要用setter來持有武當、峨眉和少林的引用。notice方法會根據不同門派發來的訊息,轉而通知給其他的門派。比如武當發來的訊息,武林盟主就會將訊息通知給少林。

客戶端呼叫
public class Client {
    public static void main(String[]args) {
        Champions champions=new Champions();
        Wudang wudang=new Wudang(champions);
        Shaolin shaolin=new Shaolin(champions);
        Emei emei=new Emei(champions);
        champions.setWudang(wudang);
        champions.setShaolin(shaolin);
        champions.setEmei(emei);
        wudang.sendAlliance("武當弟子被少林大力金剛指所殺");
        emei.sendAlliance("峨眉弟子被少林大力金剛指所殺");
        shaolin.sendAlliance("少林弟子絕不會做出這種事情");
    }
}

首先建立武林盟主類Champions 並傳入到各個門派類,接著呼叫武林盟主類的setter方法傳入各個門派類,最後呼叫各個門派的sendAlliance方法通過武林盟主類向其他門派發送訊息。

輸出結果為:
少林收到訊息:武當弟子被少林大力金剛指所殺
少林收到訊息:峨眉弟子被少林大力金剛指所殺
武當收到訊息:少林弟子絕不會做出這種事情
峨眉收到訊息:少林弟子絕不會做出這種事情

接下來給出這個例子的UML圖,如下所示。
這裡寫圖片描述

中介者模式的優缺點和使用場景

優點
符合迪米特原則,將原有的一對多的依賴變成了一對一的依賴,降低類間的耦合。

缺點
中介者會變得龐大且複雜,原本多個物件直接的相互依賴變成了中介者和多個同事類的依賴關係,同事類越多,中介者的邏輯就越複雜。

使用場景
中介者模式很容易實現呢,但是也容易誤用,不要著急使用,先要思考你的設計是否合理。
當物件之間的互動變多時,為了防止一個類會涉及修改其他類的行為,可以使用中介者模式,將系統從網狀結構變為以中介者為中心的星型結構。

3.代理模式、外觀模式和中介者模式對比

當我們學完中介者模式是不是會覺得和此前講過的代理模式和外觀模式有些類似呢?現在我們一一來將它們進行對比。

代理模式和中介者模式

代理模式是結構型設計模式,它有很多種型別,主要是在訪問物件時引入一定程度的間接性,由於有間接性,就可以附加多種的用途,比如進行許可權控制。中介者模式則是為了減少物件之間的相互耦合。雖然網上有很多代理模式和中介者模式的對比,但是在我看來這兩者實際上並沒有可比性,只是看起來有些類似罷了。

外觀模式和中介者模式

外觀模式主要是以封裝和隔離為主要任務,中介者則是調停同事類之間的關係,因此,中介者具有部分業務的邏輯控制。他們之間的主要區別為:
- 外觀模式的子系統如果脫離外觀模式還是可以執行的,而中介者模式增加了業務邏輯,同事類不能脫離中介者而獨自存在。
- 外觀模式中,子系統是不知道外觀類的存在的,而中介者模式中,每個同事類都知道中介者。
- 外觀模式將子系統的邏輯隱藏,使用者不知道子系統的存在,而中介者模式中,使用者知道同事類的存在。

參考資料
《大話設計模式》
《設計模式之禪》
《Android原始碼設計模式》

歡迎關注我的微信公眾號,第一時間獲得部落格更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,即可關注。

相關推薦

設計模式中介模式

前言 寫了很多篇設計模式的文章,才發現沒有講關於設計模式的分類,那麼這一篇就補上這一內容,順便帶來中介者模式的講解。並與此前講過的代理模式和外觀模式做對比。 1.設計模式的分類 GoF提出的設計模式總共有23種,根據目的準則分類分為三大類:

設計模式——中介模式(智慧家庭案例)

1 智慧家庭專案 智慧家庭專案: 1) 智慧家庭包括各種裝置,鬧鐘、咖啡機、電視機、窗簾 等 2) 主人要看電視時,各個裝置可以協同工作,自動完成看電視的準備工作,比如流程為:鬧鈴響起->咖啡機開始做咖啡->窗簾自動落下->電視機開始播放 傳統方案解決智慧家庭管理問題

設計模式二十三——中介模式

設計模式 中介者模式設計模式(二十三)——中介者模式一、中介者模式簡介1、中介者模式簡介 中介者模式用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立地改變它們之間的交互。 中介者模式中,每個同事對象維護一個中介者,當要進行通信時,每個具體的同

設計模式建造模式

用程式畫一個小人,這在遊戲程式裡非常常見。現在簡單一點,要求是小人要有頭、身體、兩手、兩腳就可以了。 第一版  Pen p = new Pen (Color.Yellow); Graphics gThin = pictureBox1.CreateGraphics();

設計模式-第中介模式

1. 定義       中介者模式的英文定義:Define an object that encapsulates how a set of objects interact.Mediator promotes loose couping by keeping objects

C++學習經歷建造模式

建造者模式 將產品的內部表象和產品的生產過程分割開來,從而使一個建造過程生成具有不同的內部表象的產品物件。建造者模式使得產品內部表象可以獨立的變化,客戶不必知道產品內部實現的細節。建造者模式可以強制實行一種分步驟進行的建造過程。 例子:一個房子(House)有門(Door)和牆(Wall),

我與C++設計模式——觀察模式

毋庸置疑,observer模式的地位是十分重要的,此處省略一些套話,那麼什麼是observer模式,他在幫我們解決什麼問題或者說他在面對什麼情形進行設計的。 observer模式要解決的問題是,建立一個一對多的依賴關係,並且做到當“一”變化的時候,“多”能夠及時作出相應的響

Java設計模式----觀察模式

觀察者模式 一、定義 二、結構 具體案例 推模型和拉模型 三、Java提供的對觀察者模式的支援 Observer介面 Observable類 一、定義 觀察者模式是物件的行為模式,又叫釋出-訂閱(Publish/Subscribe)模式

Android設計模式-觀察模式

觀察者模式是一種使用頻率非常高的設計模式,最常用的地方就是訂閱-釋出系統。 這個模式的重要作用就是將觀察者和被觀察者解耦,使他們之間的依賴更小甚至沒有。 定義 定義物件一種一對多的依賴關係,使得每當一個物件改變狀態,則所有依賴於他的物件都會得到通知

設計模式裝飾模式Decorator-結構型

裝飾者模式Decorator 在程式開發中,有時候開發人員會使用繼承來擴充套件物件的功能,使用者的需求是多變的,也就造成了使用繼承會造成程式碼的大範圍改動,其實擴充套件物件的功能,採用組合比繼承要好的多,當用戶需要變動時,只要將物件組合發生變化就可以了,不會大

一個故事貫穿設計模式中介模式

   這裡記錄的是中介者模式。  在解耦上面具有重要的意義。 包結構: 類結構: 測試入口: package com.automannn.design_mode.mediator.test; import com.automannn.design

設計模式中介模式

中介者模式(Mediator):用一箇中介物件來封裝一系列的物件互動。中介者使各物件不需要顯示地相互引用,從未使其耦合鬆散,而且可以獨立地改變他們之間的互動 類圖的來源: public abstract class Mediator { public

C++設計模式中介模式

中介者模式 用一箇中介物件來封裝一系列的物件互動。中介者使個各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。 本文講解中介者模式框架,程式碼使用C++語言描述,程式碼存在的不足或問題有望各位指出。 中介者模式程式碼框

設計模式筆記 —— 中介模式

中介者模式(Mediator):用一箇中介者物件來封裝一系列的物件互動。中介者物件使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立的改變它們之間的互動。中介者模式很容易在系統中應用,也很容易在系統中誤用。當系統出現了“多對多”互動複雜的物件群時,不要急於使用中介者

軟體設計模式學習中介模式

> 對於那些存在物件之間複雜互動關係的系統,中介者模式提供了一種簡化複雜互動的解決方案,即通過引入一箇中介者,將原本物件之間的兩兩互動轉化為每個物件與中介者之間的互動 ## 模式動機 以微信聊天為例,可以使用者與使用者直接聊天,也可以通過微信群聊天。前者的話,使用者要和別的使用者加為好友,即使用者

設計模式——組合模式

其他 獲取 添加 http es2017 處理方式 src 所有 alt 1.描述 將對象組合成樹形結構一以表示“部分——整體”的層次結構。組合模式使用戶對單個對象和組合對象的使用具有一致性。 2.模式的使用 ·抽象組件(Component):是一個接口或抽象類,該接口定義

Java 設計模式系列觀察模式(Observer)

for out 其中 如果 observer 業務 ets 同時 hang Java 設計模式系列(十六)觀察者模式(Observer) 觀察者模式是對象的行為模式,又叫發布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽

代理模式 PROXY Surrogate 結構型 設計模式

代理模式 PROXY 別名Surrogate 意圖 為其他的物件提供一種代理以控制對這個物件的訪問。 代理模式含義比較清晰,就是中間人,中介公司,經紀人... 在計算機程式中,代理就表示一個客戶端不想或者不能夠直接引用一個物件 而代理物件可以在客戶端和目標物件之間起到中介

《大話設計模式》Java程式碼示例之備忘錄模式

備忘錄模式(Memonto):在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態,這樣以後就可將該物件恢復到原先儲存的狀態。 package memento; /** * 備忘錄模式(Memento) * 遊戲角色 */ public

雲端計算設計模式——實體化檢視模式

雲端計算設計模式(十四)——實體化檢視模式 產生過在一個或多個數據儲存中的資料預填充的觀點時,資料被格式化以不利於所需的查詢操作的一種方式。這種模式可以幫助支援高效的查詢和提取資料,並提高應用程式的效能。 背景和問題 何時儲存資料時,優先順序為開發者和資料管理員經常集中