前言
家庭中成员的沟通交流,班级中同学之间的交流,工作中任务的协调,当互动的对象达到一定数量后.简单的对象到对象的调用就会显得过于复杂,这个时候就需要一个中间人来承担沟通协调的角色,这就是调停者在现实中的使用场景.代码中通过调停者模式可以将复杂的多对多关系转化为简单的一对多多对一的关系,通过调停者这一服务可以极大降低代码中对像间调用的耦合度。
一、模式的定义与特点
中介者(Mediator)模式(又叫调停模式):定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。
中介者模式是一种对象行为型模式,优点:
1、降低了对象之间的耦合性,使得对象易于独立地被复用。
2、将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。
缺点:
当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。
二、模式的结构
中介者模式实现的关键是找出“中介者”。
中介者模式的角色:
1、抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
2、具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
3、抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
4、具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
三、代码演示
1抽象同事类
package demo03;
//抽象同事类
public abstract class Colleague {
//持有一个调停者对象
private Mediator mediator;
public Colleague(Mediator mediator){
this.mediator = mediator;
}
/**获取当前同事类对应的调停者对象*/
public Mediator getMediator() {
return mediator;
}
}
2同事类--光驱 CDDriver
package demo03;
//同事类——光驱
public class CDDriver extends Colleague{
//光驱读取出来的数据
private String data = "";
public CDDriver(Mediator mediator) {
super(mediator);
}
/**获取光盘读取出来的数据*/
public String getData() {
return data;
}
/**读取光盘*/
public void readCD(){
//逗号前是视频显示的数据,逗号后是声音
this.data = "One Piece,海贼王我当定了";
//通知主板,自己的状态发生了改变
getMediator().changed(this);
}
}
3同事类--CPU
package demo03;
//同事类——CPU
public class CPU extends Colleague {
//分解出来的视频数据
private String videoData = "";
//分解出来的声音数据
private String soundData = "";
public CPU(Mediator mediator) {
super(mediator);
}
/**获取分解出来的视频数据*/
public String getVideoData() {
return videoData;
}
/**获取分解出来的声音数据*/
public String getSoundData() {
return soundData;
}
/**处理数据,把数据分成音频和视频的数据*/
public void executeData(String data){
//把数据分解开,前面是视频数据,后面是音频数据
String[] array = data.split(",");
this.videoData = array[0];
this.soundData = array[1];
//通知主板,CPU完成工作
getMediator().changed(this);
}
}
4同事类--显卡 VideoCard
package demo03;
//同事类——显卡
public class VideoCard extends Colleague {
public VideoCard(Mediator mediator){
super(mediator);
}
/**显示视频数据*/
public void showData(String data){
System.out.println("您正在观看的是:"+data);
}
}
5同事类--声卡SoundCard
package demo03;
//同事类——声卡
public class SoundCard extends Colleague {
public SoundCard(Mediator mediator) {
super(mediator);
}
/**按照声频数据发出声音*/
public void soundData(String data){
System.out.println("画外音:" + data);
}
}
6抽象调停者类Mediator
package demo03;
//抽象调停者类
public interface Mediator {
/**
* 同事对象在自身改变的时候来通知调停者方法
* 让调停者去负责相应的与其他同事对象的交互
*/
public void changed(Colleague c);
}
7具体调停者类MainBoard
package demo03;
//具体调停者类
public class MainBoard implements Mediator {
//需要知道要交互的同事类——光驱类
private CDDriver cdDriver = null;
//需要知道要交互的同事类——CPU类
private CPU cpu = null;
//需要知道要交互的同事类——显卡类
private VideoCard videoCard = null;
//需要知道要交互的同事类——声卡类
private SoundCard soundCard = null;
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;
}
public void changed(Colleague c) {
if (c instanceof CDDriver) {
//表示光驱读取数据了
this.opeCDDriverReadData((CDDriver) c);
}
else if(c instanceof CPU) {
this.opeCPU((CPU) c);
}
}
/**处理光驱读取数据以后与其他对象的交互*/
private void opeCDDriverReadData(CDDriver cd){
//先获取光驱读取的数据
String data = cd.getData();
//把这些数据传递给CPU进行处理
cpu.executeData(data);
}
/**处理CPU处理完数据后与其他对象的交互*/
private void opeCPU(CPU cpu){
//先获取CPU处理后的数据
String videoData = cpu.getVideoData();
String soundData = cpu.getSoundData();
//把这些数据传递给显卡和声卡展示出来
videoCard.showData(videoData);
soundCard.soundData(soundData);
}
}
8客户端Client
package demo03;
//客户端类
public class Client {
public static void main(String[] args) {
//创建调停者——主板
MainBoard mediator = new MainBoard();
//创建同事类
CDDriver cd = new CDDriver(mediator);
CPU cpu = new CPU(mediator);
VideoCard vc = new VideoCard(mediator);
SoundCard sc = new SoundCard(mediator);
//让调停者知道所有同事
mediator.setCdDriver(cd);
mediator.setCpu(cpu);
mediator.setVideoCard(vc);
mediator.setSoundCard(sc);
//开始看电影,把光盘放入光驱,光驱开始读盘
cd.readCD();
}
}
测试结果
总结
通过调停者模式可以有效的带来下面的几个有点
1.组件间的耦合度降低
2. 多对多的复杂模型变成一对多的简单模型
3. 组件间的交互集中控制
调停者模式使控制集中化,所有的交互行为都集中在调停者类中,但随着调停者类变的日益庞大,其维护成本会越来越大