中介者模式的定義
用一個(gè)中介對(duì)象來封裝一系列的對(duì)象交互。中介者使得各對(duì)象不需要顯示的相互引用,從而使其松散耦合,而且可以獨(dú)立的改變他們之間的交互。
中介者模式的本質(zhì)
封裝交互。
中介者模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 松散耦合。多個(gè)對(duì)象之間的交互封裝到一個(gè)里面,避免了牽一發(fā)而動(dòng)全身。
集中控制交互。 - 多對(duì)多變成一對(duì)多。引入中介者之后,從多對(duì)多變成雙向一對(duì)多。
缺點(diǎn)
- 太復(fù)雜的中介者會(huì)難以維護(hù)
示例1
public abstract class Colleague {
/**
* 持有中介者對(duì)象,每一個(gè)同事類都知道他的中介者對(duì)象
*/
private Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
public Mediator getMediator() {
return mediator;
}
}
public class ConcreteColleagueA extends Colleague {
public ConcreteColleagueA(Mediator mediator) {
super(mediator);
}
/**
* 示意方法
*/
public void someOperation() {
getMediator().changed(this);
}
}
public class ConcreteColleagueB extends Colleague {
public ConcreteColleagueB(Mediator mediator) {
super(mediator);
}
/**
* 示意方法
*/
public void someOperation() {
getMediator().changed(this);
}
}
/**
* 中介者,定義各個(gè)同事對(duì)象通信的接口
*/
public interface Mediator {
/**
* 同時(shí)對(duì)象在自身改變的時(shí)候來通知中介者方法
* 讓中介者負(fù)責(zé)相應(yīng)的與其他同事對(duì)象的交互
* @param colleague 同事對(duì)象自身。好讓中介者對(duì)象通過對(duì)象實(shí)例去獲取同事對(duì)象的狀態(tài)。
*/
void changed(Colleague colleague);
}
public class ConcreteMediator implements Mediator {
/**持有并維護(hù)同事A*/
private ConcreteColleagueA colleagueA;
/**持有并維護(hù)同事B*/
private ConcreteColleagueB colleagueB;
@Override
public void changed(Colleague colleague) {
//某個(gè)同事對(duì)象發(fā)生了變化,通常是與其他同事對(duì)象交互。
//具體協(xié)調(diào)相應(yīng)的同事對(duì)象來實(shí)現(xiàn)協(xié)作行為。
}
public void setColleagueA(ConcreteColleagueA colleagueA) {
this.colleagueA = colleagueA;
}
public void setColleagueB(ConcreteColleagueB colleagueB) {
this.colleagueB = colleagueB;
}
}
示例2
實(shí)際開發(fā)中通常去掉同事對(duì)象的父類。通常不定義Mediator接口,把具體的中介者實(shí)現(xiàn)成單例。同事對(duì)象也不再持有中介者,而是用到就去獲取。中介者也不再持有同事對(duì)象,而是傳參等方式獲取。
public abstract class Colleague {
// ~屬性
// =========================================
private Mediator mediator;
// ~構(gòu)造器
// =========================================
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
// ~方法
// =========================================
public Mediator getMediator() {
return mediator;
}
}
public class CDDriver extends Colleague {
// ~屬性
// =========================================
/**光驅(qū)讀取出來的數(shù)據(jù)*/
private String data = "";
// ~構(gòu)造器
// =========================================
public CDDriver(Mediator mediator) {
super(mediator);
}
// ~方法
// =========================================
/**讀取光盤*/
public void readCD() {
this.data = "設(shè)計(jì)模式,值得好好研究";
this.getMediator().changed(this);
}
// ~getter
// =========================================
public String getData() {
return this.data;
}
}
public class CPU extends Colleague {
// ~屬性
// =========================================
/**分解出來的視頻數(shù)據(jù)*/
private String vedioData;
/**分解出來的聲音數(shù)據(jù)*/
private String soundData;
// ~構(gòu)造器
// =========================================
public CPU(Mediator mediator) {
super(mediator);
}
// ~方法
// =========================================
/**
* 處理數(shù)據(jù),把數(shù)據(jù)分成音頻和視頻的數(shù)據(jù)
* @param data
*/
public void executeData(String data) {
String[] ss = data.split(",");
this.vedioData = ss[0];
this.soundData = ss[1];
getMediator().changed(this);
}
// ~getter
// =========================================
public String getVedioData() {
return vedioData;
}
public String getSoundData() {
return soundData;
}
}
public class VideoCard extends Colleague {
// ~構(gòu)造器
// =========================================
public VideoCard(Mediator mediator) {
super(mediator);
}
// ~方法
// =========================================
public void showData(String data) {
System.out.println("您正在觀看的是:"+data);
}
}
public class SoundCard extends Colleague {
// ~構(gòu)造器
// =========================================
public SoundCard(Mediator mediator) {
super(mediator);
}
// ~方法
// =========================================
public void soundData(String data) {
System.out.println("畫外音"+data);
}
}
/**
* 中介者,定義各個(gè)同事對(duì)象通信的接口
*/
public interface Mediator {
/**
* 同時(shí)對(duì)象在自身改變的時(shí)候來通知中介者方法
* 讓中介者負(fù)責(zé)相應(yīng)的與其他同事對(duì)象的交互
* @param colleague 同事對(duì)象自身。好讓中介者對(duì)象通過對(duì)象實(shí)例去獲取同事對(duì)象的狀態(tài)。
*/
void changed(Colleague colleague);
}
public class MotherBoard implements Mediator {
// ~屬性
// =========================================
/**
* 需要知道要交互的同事類-光驅(qū)類
*/
private CDDriver cdDriver = null;
/**
* 需要知道要交互的同事類-CPU類
*/
private CPU cpu = null;
/**
* 需要知道要交互的同事類-顯卡類
*/
private VideoCard videoCard = null;
/**
* 需要知道要交互的同事類-聲卡類
*/
private SoundCard soundCard = null;
// ~方法
// =========================================
@Override
public void changed(Colleague colleague) {
if (colleague == cdDriver) {
//表示光驅(qū)讀數(shù)據(jù)了
this.opeCDDriverReadData((CDDriver)colleague);
} else if (colleague == cpu) {
//表示CPU處理完了
this.opeCpu((CPU)colleague);
}
}
private void opeCDDriverReadData(CDDriver cd) {
//調(diào)用方式時(shí),光驅(qū)讀完數(shù)據(jù),在這里獲取
String data = cd.getData();
//然后將數(shù)據(jù)傳給CPU,讓CPU來處理
this.cpu.executeData(data);
}
private void opeCpu(CPU cpu) {
//調(diào)用方式時(shí),cpu處理完數(shù)據(jù)了,在這里獲取
String videoData = cpu.getVedioData();
String soundData = cpu.getSoundData();
//然后傳給聲卡和顯卡來顯示
this.videoCard.showData(videoData);
this.soundCard.soundData(soundData);
}
// ~setter
// =========================================
public MotherBoard setCdDriver(CDDriver cdDriver) {
this.cdDriver = cdDriver;
return this;
}
public MotherBoard setCpu(CPU cpu) {
this.cpu = cpu;
return this;
}
public MotherBoard setVideoCard(VideoCard videoCard) {
this.videoCard = videoCard;
return this;
}
public MotherBoard setSoundCard(SoundCard soundCard) {
this.soundCard = soundCard;
return this;
}
}
public class TestClient {
public static void main(String[] args) {
// 創(chuàng)建中介者 --- 主板對(duì)象
MotherBoard mediator = new MotherBoard();
// 創(chuàng)建同事類
CDDriver cdDriver = new CDDriver(mediator);
CPU cpu = new CPU(mediator);
VideoCard videoCard = new VideoCard(mediator);
SoundCard soundCard = new SoundCard(mediator);
// 讓中介者知道所有的同事
mediator.setCdDriver(cdDriver)
.setCpu(cpu)
.setVideoCard(videoCard)
.setSoundCard(soundCard);
// 開始看電影放入光驅(qū)
cdDriver.readCD();
}
}