設計模式系列:中介者模式
引入
1.案例:
假設計算機1,2,3,4之間要相互通訊。
2.面向實現程式設計方案:
類Computer1中要儲存類Computer2、類Computer3和類Computer4例項,才能呼叫Computer2、Computer3、Computer4方法中的Comunicate方法。
。。。
。。。
。。。
具體圖示如下:
3.面向設計程式設計方案:
建立一箇中介者,保有類Computer1,類Computer2,類Computer3,類Computer4物件,每個Computer只需要跟中介者打交道,即可和其他的Computer通訊。具體的圖示如下:
明顯可以看到面向設計的方案通過增加一層(中介層)可以明顯較少類間的耦合。
一.名稱
二.問題(為了解決什麼問題)
中介者模式適合於多個物件之間緊密耦合的情況,緊密耦合的標準是:在類圖中出現了蜘蛛網狀結構。在這種情況下一定考慮使用中介者模式,這有利於把蜘蛛網樹立成為星型結構,使原本複雜混亂的關係變得清晰簡單。生活中常見的例項是:媒體閘道器、中介服務(如鏈家中介)等。
三.解決方案(主要體現在uml和核心程式碼上)
定義:用一箇中介物件封裝一系列的物件互動,中介者使各物件不需要顯示地相互作用,從而使其耦合鬆散,而且可以獨立改變他們之間的互動。
其實中介者模式是一個解耦框架,主要是通過增加一層(中介層)來實現類間的解耦。
中介者模式體現的設計原則有:依賴倒置,開閉原則,迪米特法則,里氏替換原則。
抽象類與繼承——依賴倒置
抽象類——開閉原則
降低耦合——迪米特法則
抽象類——里氏替換原則
如果物件之間的聯絡呈現為網狀結構,存在大量的多對多聯絡,在網狀結構中,幾乎每個物件都需要與其他物件發生相互作用,而這種相互作用表現為一個物件與另外一個物件的直接耦合,這將導致一個過度耦合的系統。如果在一個系統中物件之間存在多對多的相互關係,我們可以將物件之間的一些互動行為從各個物件中分離出來,並集中封裝在一箇中介者物件中,並由該中介者進行統一協調,這樣物件之間多對多的複雜關係就轉化為相對簡單的一對多關係。通過引入中介者來簡化物件之間的複雜互動,中介者模式是“迪米特法則”的一個典型應用。
類圖
時序圖
其實狀態模式的Context就像一箇中介者,避免了各種state之間的互動,二把互動交給Context來處理。
四.例子
求租者 - 房屋出租中介 - 房東 的故事
同事類:
/**
* Created by annuoaichengzhang on 16/4/4.
* 求租者-房屋出租中介-房東
*/
public abstract class Person {
protected Mediator mediator;
protected String name;
public Person(Mediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
protected abstract void sendMessage(String msg);
protected abstract void getMessage(String msg);
}
/**
* Created by annuoaichengzhang on 16/4/4.
*/
public class LandLord extends Person {
public LandLord(Mediator mediator, String name) {
super(mediator, name);
}
@Override
protected void sendMessage(String msg) {
mediator.operation(this, msg);
}
@Override
protected void getMessage(String msg) {
System.out.println("房東" + super.name + "收到中介發來的訊息:" + msg);
}
}
/**
* Created by annuoaichengzhang on 16/4/4.
*/
public class Renter extends Person {
public Renter(Mediator mediator, String name) {
super(mediator, name);
}
@Override
protected void sendMessage(String msg) {
super.mediator.operation(this, msg);
}
@Override
protected void getMessage(String msg) {
System.out.println("求租者" + super.name + "收到中介發來的資訊" + msg);
}
}
中介者:
/**
* Created by annuoaichengzhang on 16/4/4.
*/
public abstract class Mediator {
protected List<Person> landlordList = new ArrayList<>();
protected List<Person> renterList = new ArrayList<>();
public void registerLandlord(Person landLord) {
landlordList.add(landLord);
}
public void registerRenter(Person renter){
renterList.add(renter);
}
public abstract void operation(Person person, String message);
}
/**
* Created by annuoaichengzhang on 16/4/4.
*/
public class HouseMediator extends Mediator {
@Override
public void operation(Person person, String message) {
// 如果是租房者,就把租房者的需求資訊傳遞給註冊了的房東們
if (person instanceof Renter) {
for (Person landlord : landlordList) {
landlord.getMessage(message);
}
} else if (person instanceof LandLord) {
// 如果是房東,就把房東的出租訊息傳遞給註冊了的求租者
for (Person renter : renterList) {
renter.getMessage(message);
}
}
}
}
client:
/**
* Created by annuoaichengzhang on 16/4/4.
*/
public class Client {
public static void main(String[] args) {
Mediator mediator = new HouseMediator();
Person landlordA, landlordB, renter;
landlordA = new LandLord(mediator, "房東a");
landlordB = new LandLord(mediator, "房東b");
renter = new Renter(mediator, "小呂");
mediator.registerLandlord(landlordA);
mediator.registerLandlord(landlordB);
mediator.registerRenter(renter);
renter.sendMessage("想在四惠東附近租套一居室,加個1500");
landlordA.sendMessage("在四惠東附近有一套兩居室要出租,租金3000,聯絡電話0101010101001");
}
}
執行結果:
房東房東a收到中介發來的訊息:想在四惠東附近租套一居室,加個1500
房東房東b收到中介發來的訊息:想在四惠東附近租套一居室,加個1500
求租者小呂收到中介發來的資訊在四惠東附近有一套兩居室要出租,租金3000,聯絡電話0101010101001
Process finished with exit code 0
五.效果(有啥優缺點)
優點:
1. 簡化了物件間的互動
缺點:
1. 在具體的中介類中包含了大量同事之間的互動細節,會導致中介類非常複雜,不易維護。
常見案例
qq群群聊
圖形介面類庫。該類庫包含若干預定義的窗格物件,例如textpane、listpane等,窗格之間不允許直接引用。基於該類庫的應用由一個包含一組窗格的視窗組成,視窗需要協調窗格之間的行為。