1、簡介
別名:調停者模式
定義:用一個中介對象來封裝一系列的對象交互,中介者使各對象不需要顯示地相互引用。從而使其耦合松散,而且可以獨立地改變它們之間的交互。
主要解決:對象與對象之間存在大量的關聯關系,這樣勢必會導致系統的結構變得很復雜,同時若一個對象發生改變,我們也需要跟蹤與之相關聯的對象,同時做出相應的處理。
何時使用:多個類相互耦合,形成了網狀結構。
如何解決:將上述網狀結構分離為星型結構。
核心思想:1、就是將網狀結構處理成星型結構
2、將多對多處理成一對多
本質:封裝對象間的交互
英文:Mediator
類型:行為型
PS:附圖示解決的問題
2、類圖及組成
(引)類圖:
組成:
● 抽象中介者(Mediator)角色:定義統一的接口用於各同事角色之間的通信,其中主要方法是一個(或多個)事件方法。
● 具體中介者(ConcreteMediator)角色:實現了抽象中介者所聲明的事件方法。具體中介者知曉所有的具體同事類,並負責具體的協調各同事對象的交互關系。
● 抽象同事類(Colleague)角色:定義出中介者到同事角色的接口。同事角色只知道中介者而不知道其余的同事角色。與其他的同事角色通信的時候,一定要通過中介者角色協作。
● 具體同事類(ConcreteColleague)角色:所有的具體同事類均從抽象同事類繼承而來。實現自己的業務,在需要與其他同事通信的時候,就與持有的中介者通信,中介者會負責與其他的同事交互。
代碼結構:
//抽象中介者類 public interface Mediator { /** * 同事對象在自身改變的時候來通知中介者的方法 * 讓中介者去負責相應的與其他同事對象的交互 */ public void changed(Colleague c); } //抽象同事類 public abstract class Colleague { //持有一個中介者對象 private Mediator mediator; /** * 構造函數 */ public Colleague(Mediator mediator){ this.mediator = mediator; } /** * 獲取當前同事類對應的中介者對象 */ public Mediator getMediator() { return mediator; } } //具體中介者類 public class ConcreteMediator implements Mediator { //持有並維護同事A private ConcreteColleagueA colleagueA; //持有並維護同事B private ConcreteColleagueB colleagueB; public void setColleagueA(ConcreteColleagueA colleagueA) { this.colleagueA = colleagueA; } public void setColleagueB(ConcreteColleagueB colleagueB) { this.colleagueB = colleagueB; } @Override public void changed(Colleague c) { /** * 某一個同事類發生了變化,通常需要與其他同事交互 * 具體協調相應的同事對象來實現協作行為 */ } } //具體同事類 public class ConcreteColleagueA extends Colleague { public ConcreteColleagueA(Mediator mediator) { super(mediator); } /** * 示意方法,執行某些操作 */ public void operation(){ //在需要跟其他同事通信的時候,通知中介者對象 getMediator().changed(this); } } public class ConcreteColleagueB extends Colleague { public ConcreteColleagueB(Mediator mediator) { super(mediator); } /** * 示意方法,執行某些操作 */ public void operation(){ //在需要跟其他同事通信的時候,通知中介者對象 getMediator().changed(this); } }
3、實例引入
假設現在有A、B、C建立了一個微信討論組,他們有什么問題就在這里討論,A在猶豫今天中午吃什么,A同學只要在討論組里問一聲就可以了,不必要直接去和B、C同學打交道,省去了很多麻煩事。怎么實現呢?
抽象中介者:
package com.designpattern.Mediator; /** * 抽象中介者類 * @author Json<<json1990@foxmail.com>> */ public interface Mediator { /** * 發送消息 */ public void chat(People p,String message); }
抽象同事類:
package com.designpattern.Mediator; /** * 抽象同事類 -- 聊天人員 * @author Json<<json1990@foxmail.com>> */ public abstract class People { //人員昵稱 private String name; //持有一個中介者對象 private Mediator mediator; /** * 構造函數 */ public People(Mediator mediator,String name){ this.mediator = mediator; this.name = name; } /** * 獲取中介者對象 */ public Mediator getMediator() { return mediator; } /** * 獲取昵稱 */ public String getName() { return name; } /** * 接收消息 */ public abstract void receive(String message); /** * 發送消息 */ public abstract void send(String message); }
3個具體同事類:
package com.designpattern.Mediator; /** * 具體同事類 -- 人員a * @author Json<<json1990@foxmail.com>> */ public class PeopleA extends People { public PeopleA(Mediator mediator,String name) { super(mediator, name); } /** * 接收消息 */ public void receive(String message){ System.out.println("【A】收到消息:【"+message+"】"); } /** * 發送消息 */ public void send(String message){ System.out.println("【A】發出消息:【"+message+"】"); } }
package com.designpattern.Mediator; /** * 具體同事類 -- 人員b * @author Json<<json1990@foxmail.com>> */ public class PeopleB extends People { public PeopleB(Mediator mediator,String name) { super(mediator, name); } /** * 接收消息 */ public void receive(String message){ System.out.println("【B】收到消息:【"+message+"】"); } /** * 發送消息 */ public void send(String message){ System.out.println("【B】發出消息:【"+message+"】"); } }
package com.designpattern.Mediator; /** * 具體同事類 -- 人員c * @author Json<<json1990@foxmail.com>> */ public class PeopleC extends People { public PeopleC(Mediator mediator,String name) { super(mediator, name); } /** * 接收消息 */ public void receive(String message){ System.out.println("【C】收到消息:【"+message+"】"); } /** * 發送消息 */ public void send(String message){ System.out.println("【C】發出消息:【"+message+"】"); } }
具體中介者實現:
package com.designpattern.Mediator; /** * 具體中介者類 * @author Json<<json1990@foxmail.com>> */ public class MessageMediator implements Mediator { //持有並維護人員A private PeopleA A; //持有並維護人員B private PeopleB B; //持有並維護人員C private PeopleC C; public void setPeopleA(PeopleA A) { this.A = A; } public void setPeopleB(PeopleB B) { this.B = B; } public void setPeopleC(PeopleC C) { this.C = C; } /** * 發送消息 */ @Override public void chat(People p,String message) { if (p instanceof PeopleA) { A.send(message); B.receive(message); C.receive(message); } else if (p instanceof PeopleB) { B.send(message); A.receive(message); C.receive(message); } else if (p instanceof PeopleC) { C.send(message); A.receive(message); B.receive(message); } } }
測試:
package com.designpattern.Mediator; /** * 測試 * @author Json<<json1990@foxmail.com>> */ public class Client { public static void main(String[] args) { MessageMediator mediator = new MessageMediator(); PeopleA a = new PeopleA(mediator,"A"); PeopleB b = new PeopleB(mediator,"B"); PeopleC c = new PeopleC(mediator,"C"); mediator.setPeopleA(a); mediator.setPeopleB(b); mediator.setPeopleC(c); mediator.chat(a, "中午吃啥飯?"); System.out.println(); mediator.chat(b,"我想吃刀削面"); System.out.println(); mediator.chat(c,"我也想吃刀削面"); System.out.println(); mediator.chat(a, "行,那中午一起去吃刀削面吧"); System.out.println(); } }
結果:
【A】發出消息:【中午吃啥飯?】
【B】收到消息:【中午吃啥飯?】
【C】收到消息:【中午吃啥飯?】
【B】發出消息:【我想吃刀削面】
【A】收到消息:【我想吃刀削面】
【C】收到消息:【我想吃刀削面】
【C】發出消息:【我也想吃刀削面】
【A】收到消息:【我也想吃刀削面】
【B】收到消息:【我也想吃刀削面】
【A】發出消息:【行,那中午一起去吃刀削面吧】
【B】收到消息:【行,那中午一起去吃刀削面吧】
【C】收到消息:【行,那中午一起去吃刀削面吧】
4、優缺點
優點:
簡化了對象之間的交互:它用中介者和同事的一對多交互代替了原來同事之間的多對多交互,一對多關系更容易理解、維護和擴展,將原本難以理解的網狀結構轉換成相對簡單的星型結構。
各同事對象之間解耦:中介者有利於各同事之間的松耦合,我們可以獨立的改變和復用每一個同事和中介者,增加新的中介者和新的同事類都比較方便,更好地符合“開閉原則”。
減少子類生成:中介者將原本分布於多個對象間的行為集中在一起,改變這些行為只需生成新的中介者子類即可,這使各個同事類可被重用,無須對同事類進行擴展。
缺點:
中介者會龐大,變得復雜難以維護。
5、使用場景
1、對象間的交互雖定義明確然而非常復雜,導致一組對象彼此相互依賴而且難以理解。
2、因為對象引用了許多其他對象並與其通信,導致對象難以復用。
3、想要定制一個分布在多個類中的邏輯或者行為,又不想生成太多子類。
實際應用:
Mediator模式在事件驅動類應用中比較多,例如聊天、消息傳遞等等,需要有一個MessageMediator,專門負責request/reponse之間任務的調節。
MVC模式中,Controller是一種Mediator。
JDK的具體應用:
java.util.Timer
java.util.concurrent.Executor#execute()
java.util.concurrent.ExecutorService#submit()
java.lang.reflect.Method#invoke()
.......
6、中介者模式和外觀模式
1、外觀模式是結構型模式,中介者模式是行為型模式;
2、中介者模式主要用來封裝多個平等對象之間相互的交互,多用在系統內部的多個模塊之間;
外觀模式旨在提供一個高層次的接口,封裝的是單向的交互,是從客戶端訪問系統的調用,沒有從系統中來訪問客戶端的調用;
外觀模式協議是單向,中介者模式協議是雙向;
3、中介者模式的實現里面,是需要實現具體的交互功能的;而外觀模式的實現里面,一般是組合調用或是轉調內部實現的功能,通常外觀模式不添加額外的功能;
4、中介者模式的目的主要是松散多個模塊之間的耦合,把這些耦合關系全部放到中介者中去實現;而外觀模式的目的是簡化客戶端的調用;
7、總結
中介者模式很容易在系統中應用,也很容易在系統中誤用。當系統出現了“多對多”交互復雜的對象群,不要急於使用中介者模式,而先要思考在設計上是不是合理↓↓↓
PS:不應當在職責混亂的時候使用;
PS:源碼地址 https://github.com/JsonShare/DesignPattern/tree/master
PS:原文地址 http://www.cnblogs.com/JsonShare/p/7263876.html