中介者模式的定义
用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显示的相互引用,从而使其松散耦合,而且可以独立的改变他们之间的交互。
中介者模式的本质
封装交互。
中介者模式的优缺点
优点
- 松散耦合。多个对象之间的交互封装到一个里面,避免了牵一发而动全身。
集中控制交互。 - 多对多变成一对多。引入中介者之后,从多对多变成双向一对多。
缺点
- 太复杂的中介者会难以维护
示例1
public abstract class Colleague {
/**
* 持有中介者对象,每一个同事类都知道他的中介者对象
*/
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);
}
}
/**
* 中介者,定义各个同事对象通信的接口
*/
public interface Mediator {
/**
* 同时对象在自身改变的时候来通知中介者方法
* 让中介者负责相应的与其他同事对象的交互
* @param colleague 同事对象自身。好让中介者对象通过对象实例去获取同事对象的状态。
*/
void changed(Colleague colleague);
}
public class ConcreteMediator implements Mediator {
/**持有并维护同事A*/
private ConcreteColleagueA colleagueA;
/**持有并维护同事B*/
private ConcreteColleagueB colleagueB;
@Override
public void changed(Colleague colleague) {
//某个同事对象发生了变化,通常是与其他同事对象交互。
//具体协调相应的同事对象来实现协作行为。
}
public void setColleagueA(ConcreteColleagueA colleagueA) {
this.colleagueA = colleagueA;
}
public void setColleagueB(ConcreteColleagueB colleagueB) {
this.colleagueB = colleagueB;
}
}
示例2
实际开发中通常去掉同事对象的父类。通常不定义Mediator接口,把具体的中介者实现成单例。同事对象也不再持有中介者,而是用到就去获取。中介者也不再持有同事对象,而是传参等方式获取。
public abstract class Colleague {
// ~属性
// =========================================
private Mediator mediator;
// ~构造器
// =========================================
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
// ~方法
// =========================================
public Mediator getMediator() {
return mediator;
}
}
public class CDDriver extends Colleague {
// ~属性
// =========================================
/**光驱读取出来的数据*/
private String data = "";
// ~构造器
// =========================================
public CDDriver(Mediator mediator) {
super(mediator);
}
// ~方法
// =========================================
/**读取光盘*/
public void readCD() {
this.data = "设计模式,值得好好研究";
this.getMediator().changed(this);
}
// ~getter
// =========================================
public String getData() {
return this.data;
}
}
public class CPU extends Colleague {
// ~属性
// =========================================
/**分解出来的视频数据*/
private String vedioData;
/**分解出来的声音数据*/
private String soundData;
// ~构造器
// =========================================
public CPU(Mediator mediator) {
super(mediator);
}
// ~方法
// =========================================
/**
* 处理数据,把数据分成音频和视频的数据
* @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 {
// ~构造器
// =========================================
public VideoCard(Mediator mediator) {
super(mediator);
}
// ~方法
// =========================================
public void showData(String data) {
System.out.println("您正在观看的是:"+data);
}
}
public class SoundCard extends Colleague {
// ~构造器
// =========================================
public SoundCard(Mediator mediator) {
super(mediator);
}
// ~方法
// =========================================
public void soundData(String data) {
System.out.println("画外音"+data);
}
}
/**
* 中介者,定义各个同事对象通信的接口
*/
public interface Mediator {
/**
* 同时对象在自身改变的时候来通知中介者方法
* 让中介者负责相应的与其他同事对象的交互
* @param colleague 同事对象自身。好让中介者对象通过对象实例去获取同事对象的状态。
*/
void changed(Colleague colleague);
}
public class MotherBoard implements Mediator {
// ~属性
// =========================================
/**
* 需要知道要交互的同事类-光驱类
*/
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) {
//表示光驱读数据了
this.opeCDDriverReadData((CDDriver)colleague);
} else if (colleague == cpu) {
//表示CPU处理完了
this.opeCpu((CPU)colleague);
}
}
private void opeCDDriverReadData(CDDriver cd) {
//调用方式时,光驱读完数据,在这里获取
String data = cd.getData();
//然后将数据传给CPU,让CPU来处理
this.cpu.executeData(data);
}
private void opeCpu(CPU cpu) {
//调用方式时,cpu处理完数据了,在这里获取
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) {
// 创建中介者 --- 主板对象
MotherBoard mediator = new MotherBoard();
// 创建同事类
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);
// 开始看电影放入光驱
cdDriver.readCD();
}
}