1. 定义
- 又称:调解者/调停者模式
- 包装了一系列对象相互作用的方式,用来降低这些对象之间的通信复杂性,从中协调充当牵线搭桥的作用
2. 使用场景
- 系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱,而且难以复用该对象
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类
3. 优缺点
- 优点:
- 使得这些对象不必相互明显作用,从而实现松耦合
- 当某些对象之间的作用发生改变时,不会影响其他对象,保证独立变化
- 将多对多的相互作用转化为一对多的相互作用,由复杂的网状结构变为以中介者为中心的星型结构
- 缺点:中介者会庞大,变得复杂难以维护
4. Android源码中的使用
- Android的锁屏(Keyguard)是一个非常重要的模块。包含的功能有:解锁(指纹、图案、PIN等)、锁屏通知显示、快速启动相机、快速拨号、显示日期/时间等。其中KeyguardViewMediator是整个待机解/锁屏业务的调度器,负责调度锁屏界面的相关动作及查询解锁屏状态,其中包含了许多XXXManager的管理器成员变量,如AlarmManager,StatusBarManager,PowerManager等,KeyguardViewMediator则是充当中介者协调这些管理器的状态改变
- Binder机制中ServiceManager和Binder Driver充当中介者,协调服务端与客户端
5. 实例演示
以电脑播放CD为例,主板作为中介者,协调cpu,内存,显卡,声卡,光驱等模块,这些模块间等通信都是通过主板进行等,对其中任何一个进行更改(如升级换新)都不会影响到其他模块,只需要调整其与主板间到连接即可,主板再通知其他模块作出相应调整
- 首先创建一个中介者基类
//抽象的中介者
abstract class Mediator {
//各模块改变时通知中介者的方法,由中介者通知其他模块
public abstract void changed(Colleague c);
}
- 创建主板类
//中介者实现类:主板
class MainBoard extends Mediator {
private CDDevice mCDDevice;//光驱
private CPU mCPU;//cpu
private SoundCard mSoundCard;//声卡
private GraphicsCard mGraphicsCard;//显卡
@Override
public void changed(Colleague c) {
if (c == mCDDevice) {
//光驱读取完数据
handleCD((CDDevice) c);
} else if (c == mCPU) {
//cpu解析完数据
handleCPU((CPU) c);
}
}
//处理cpu读取数据后与其他设备的交互
private void handleCPU(CPU cpu) {
mSoundCard.soundPlay(cpu.getDataSound());
mGraphicsCard.videoPlay(cpu.getDataVideo());
}
//处理光驱读取数据后与其他设备的交互
private void handleCD(CDDevice cdDevice) {
mCPU.decodeData(cdDevice.read());
}
public void setCDDevice(CDDevice CDDevice) {
mCDDevice = CDDevice;
}
public void setCPU(CPU CPU) {
mCPU = CPU;
}
public void setSoundCard(SoundCard soundCard) {
mSoundCard = soundCard;
}
public void setGraphicsCard(GraphicsCard graphicsCard) {
mGraphicsCard = graphicsCard;
}
}
- 创建一个模块基类,相当于实际中各模块与主板连接的硬件接口协议或软件驱动协议,这些都是有统一标准的
//抽象同事类
abstract class Colleague {
protected Mediator mMediator;//每个同事都该知道其中介者
public Colleague(Mediator mediator) {
mMediator = mediator;
}
}
- 各模块的实现类,CPU,光驱,声卡,显卡等, 从代码中可以看到,各模块只负责自己职责范围的工作,将处理结果通知给主板,由主板来协调下一步需要做什么,模块间实现解耦
//CPU: 负责从主板传递来的音视频数据的解码
class CPU extends Colleague {
private String dataVideo, dataSound;//视频音频数据
public CPU(Mediator mediator) {
super(mediator);
}
public String getDataVideo() {
return dataVideo;
}
public String getDataSound() {
return dataSound;
}
public void decodeData(String data) {
//分割音视频数据
String[] tmp = data.split(",");
//解析以视频数据
dataVideo = tmp[0];
dataSound = tmp[1];
//告诉中介者自身状态改变
mMediator.changed(this);
}
}
//光驱: 负责读取光盘的数据,并提供给主板
class CDDevice extends Colleague {
public String data;//视频数据
public CDDevice(Mediator mediator) {
super(mediator);
}
//读取视频数据
public String read() {
return data;
}
//加载视频数据
public void load() {
data = "视频数据,音频数据";
//通知中介者
mMediator.changed(this);
}
}
//显卡, 声卡: 负责播放视频和音频
class GraphicsCard extends Colleague {
public GraphicsCard(Mediator mediator) {
super(mediator);
}
//播放视频
public void videoPlay(String data) {
LjyLogUtil.i("videoPlay:" + data);
}
}
class SoundCard extends Colleague {
public SoundCard(Mediator mediator) {
super(mediator);
}
public void soundPlay(String data) {
LjyLogUtil.i("soundPlay:" + data);
}
}
- 创建实例,完成播放CD的流程
private void methodMediatorPattern() {
//1.构造主板对象
MainBoard mainBoard = new MainBoard();
//2.构造各个模块设备
CDDevice cdDevice = new CDDevice(mainBoard);
CPU cpu = new CPU(mainBoard);
GraphicsCard graphicsCard = new GraphicsCard(mainBoard);
SoundCard soundCard = new SoundCard(mainBoard);
//3.将各个模块安装到主板
mainBoard.setCDDevice(cdDevice);
mainBoard.setCPU(cpu);
mainBoard.setGraphicsCard(graphicsCard);
mainBoard.setSoundCard(soundCard);
//4.执行cd播放:
cdDevice.load();
}
上面执行cd播放的具体流程如下:
光驱调用load()方法读取cd,读取完成后通知主板-->主板收到通知后,将光驱读取到的数据传给cpu去解码-->cpu解析数据,解析完成后通知主板-->主板收到通知后,将cpu解码出的音视频流传给声卡, 显卡播放-->声卡显卡播放音视频, 至此就完成来cd的播放
网友评论