概念
大家都知道,电脑里面各个配件之间的交互,主要是通过主板完成的;试想一下,如果没有主板会怎样呢?如果电脑里面没有主板,那么各个配件之间就必须自行相互交互,以互相传送数据。理论上说,基本上各个配件相互之间都存在交互数据的可能。
这也太复杂了,这还没有完呢,由于各个配件的接口不同,那么相互之间交互的时候,还必须把数据接口进行转换才能匹配上,那就更恐怖了。所幸有了主板,各个配件的交互完全通过主板来完成,每个配件都只需和主板交互,而主板知道如何和所有的配件打交道,那就简单多了。
中介者模式的定义: 用一个中介对象来封装一系列的对象交互。中介者使得个对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
类图
角色
- Mediator(抽象中介者):中介者接口,该接口用于与各同事对象之间交互需要的方法,可以是公共的通信方法,比如changed方法,大家都用,也可以是小范围的交互方法。
- ConcreteMediator(具体中介者):通过协调各同事对象来实现协作行为,并负责具体的协调个同事对象的交互关系。
- Colleague(抽象同事类):它定义各个同事类公有的方法,并声明了一些抽象方法来供子类实现,同时它维持了一个对抽象中介者类的引用,其子类可以通过该引用来与中介者通信。
- ConcreteColleague(具体同事类):具体的同事类;每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信;在具体同事类中实现了在抽象同事类中声明的抽象方法。
案例
使用中介者模式实现电脑数据交互的过程
package com.hanker.oop7;
//中介者接口,定义各个同事对象通信的接口
interface Mediator{
/**
* 同事对象在自身改变的时候来通知中介者的方法
* 让中介者去负责相应的与其他同事对象的交互
* @param colleague 同事对象自身,好让中介者对象通过对象实例去获取同事对象的状态
*/
public void changed(Colleage colleague);
}
abstract class Colleage{
private Mediator mediator;
public Colleage(Mediator mediator) {
this.mediator = mediator;
}
public Mediator getMediator() {
return this.mediator;
}
}
//具体同事类
class CDDriver extends Colleage{
public CDDriver(Mediator mediator) {
super(mediator);
}
private String data = "";//光驱读取的数据
/**
* 获取光驱读取出来的数据
* @return 光驱读取出来的数据
*/
public String getData() {
return this.data;
}
//读取光盘:业务方法,也是和中介者交互的方法
public void readCD() {
this.data = "设计模式,值得好好研究";
this.getMediator().changed(this);
}
}
//CPU同事类
class CPU extends Colleage{
public CPU(Mediator mediator) {
super(mediator);
}
private String videoData;//解析的视频数据
private String soundData;//解析的音频数据
public String getVideoData() {
return videoData;
}
public String getSoundData() {
return soundData;
}
//处理数据,把数据分成音频和视频数据
public void executeData(String data) {
//把数据分解开,前面的是视频,后面的是音频
String [] ss = data.split(",");
this.videoData = ss[0];
this.soundData = ss[1];
//通知主板,CPU的工作完成后
this.getMediator().changed(this);
}
}
//显卡同事类
class VideoCard extends Colleage{
public VideoCard(Mediator mediator) {
super(mediator);
}
//显示数据
public void showData(String data) {
System.out.println("您正观看的是:"+data);
}
}
//声卡同事类
class SoundCard extends Colleage{
public SoundCard(Mediator mediator) {
super(mediator);
}
//发出声音
public void soundData(String data) {
System.out.println("画外音:"+data);
}
}
//主板类,实现中介者接口
class MotherBoard implements Mediator{
private CDDriver cdDriver;
private CPU cpu;
private VideoCard videoCard;
private SoundCard soundCard;
public void setCdDriver(CDDriver cdDriver) {
this.cdDriver = cdDriver;
}
public void setCpu(CPU cpu) {
this.cpu = cpu;
}
public void setVideoCard(VideoCard videoCard) {
this.videoCard = videoCard;
}
public void setSoundCard(SoundCard soundCard) {
this.soundCard = soundCard;
}
@Override
public void changed(Colleage colleague) {
if(colleague == cdDriver) {
//表示光驱读取数据了
this.openCDDriverReadData((CDDriver) colleague);
}else if(colleague == cpu) {
//表示CPU处理完了
this.openCUP((CPU) colleague);
}
}
//处理光驱读取数据以后与其他对象的交互
private void openCDDriverReadData(CDDriver cdDriver) {
//1.先获取光驱读取的数据
String data = cdDriver.getData();
//2.把这些数据传递个CPU进行处理
this.cpu.executeData(data);
}
//处理CPU处理完数据后与其他对象的交互
private void openCUP(CPU cpu) {
//1.先获取CPU处理后的数据
String videoData = cpu.getVideoData();
String soundData = cpu.getSoundData();
//2.把这些数据传递给显卡和声卡显示出来
this.videoCard.showData(videoData);
this.soundCard.soundData(soundData);
}
}
public class MediatorPatternDemo {
public static void main(String[] args) {
//1.创建中介者——主板对象
MotherBoard mediator = new MotherBoard();
//2.创建同事类
CDDriver cd = new CDDriver(mediator);
CPU cpu = new CPU(mediator);
VideoCard vc = new VideoCard(mediator);
SoundCard sc = new SoundCard(mediator);
//3.让中介者知道所有的同事
mediator.setCdDriver(cd);
mediator.setCpu(cpu);
mediator.setVideoCard(vc);
mediator.setSoundCard(sc);
//4.开始看电影,把光盘放入光驱,光驱开始读盘
cd.readCD();
}
}
时序图:
优缺点
优点
- 使用中介者模式可以把对个同事对象之间的交互封装到中介者对象里面,从而使得同事对象之间松散耦合。
- 中介者模式可以将原先多对多的同事对象关系变成中介者对象一对多同事对象的关系,这样会让对象之间的关系更容易理解和实现。
- 同事对象之间的交互都被封装到中介者对象里面集中管理,集中了控制交互。当交互发生改变时,着重修改的是中介者对象。当需要扩展中介者对象时,其他同事对象不需要做修改。
缺点
- 过度集中化,这是中介者模式潜在的缺点。如果同事对象多了,交互也复杂了。那么这些交互全部集中到中介者对象中,会导致中介者对象十分臃肿,难以管理和维护。