您的位置:首页 > 编程语言 > Java开发

【Java设计模式】· 调停者模式(Mediator Pattern)

2015-08-10 13:04 489 查看

调停者/中介者模式:

1.当多个对象需要互相交互的时候,因为情况太混乱很容易出错,而且出错后也不容易去查复修改(因为可能一个类中调用了多个其他类的方法等..),这时候需要用到调停者模式。

2.调停者模式:简单说就是把所有需要交互的类的需求(命令)集中到一个Mediator (中介) 类中,以后所有的布置/修改命令都在这个Mediator中进行,这样会使整个项目看起来易修改,扩展性高,查找问题容易等。



Mediator (中介者/调停者):是一个接口类

MainBoard(中介者/调停者的具体类):在MainBoard里面必须有各各需要交互的成员变量



Colleague(同事类,这里代表电脑组件):电脑组件的父类(非抽象),含有成员变量Mediator,声明一个Colleague时必须赋予它一个Mediator



CDDriver,CPU,SoundCard,VideoCard(同事类的具体类,这里是各种电脑部件):具体的电脑组件类,声明一个这样的类时必须赋予它一个Mediator

3.例子:如一台电脑需要播放影片,涉及到的部件有:CPU , CDDriver , SoundCard , VideoCard等,这4类部件在工作过程中需要重复互相交互,所以在电脑中又存在一个MainBoard(主板)作为它们的中介者,下面看下具体实现。

创建PcComponents作为电脑中各各部件的父类,CPU等都必须继承它

package pers.reus.model.colleague;

import pers.reus.model.mediator.Mediator;

//Colleague同事类,这里称作电脑组件类
public class PcComponents {
//声明中介者
Mediator mediator;

//声明类时必须赋予它一个中介者
public PcComponents(Mediator mediator){
this.mediator = mediator;
}

//获得中介者
public Mediator getMediator(){
return this.mediator;
}
}


中介者/调停者类

package pers.reus.model.mediator;

import pers.reus.model.colleague.PcComponents;

//中介者类
public interface Mediator {
//changed()的作用很明显,当其他硬件做出改变是,通过changed()通知中介者
public void changed(PcComponents p);
}


具体的电脑组件类,创建一个CD驱动类,播放CD就是从这个类开始

package pers.reus.model.concreteColleague;

import pers.reus.model.colleague.PcComponents;
import pers.reus.model.mediator.Mediator;

public class CDDriver extends PcComponents{
//data是播放的内容
private String data = null;

//给CD驱动类设定一个中介者
public CDDriver(Mediator mediator) {
super(mediator);
}

public String getData(){
return data;
}

//readCD(),开始播放CD
public void readCD(){
//为了方便,不给函数传参,data事先定义好
this.data = "One Piece,海贼王我当定了";

//定义好之后,通知主板(中介者)
getMediator().changed(this);
}
}


具体的电脑组件类,CPU作用是接收CD驱动带来的数据,并处理好后,分给声卡类和影像类去执行

package pers.reus.model.concreteColleague;

import pers.reus.model.colleague.PcComponents;
import pers.reus.model.mediator.Mediator;

public class CPU extends PcComponents{
//CPU包含影像data和声音data
private String videoData = null;
private String soundData = null;

//给CPU设定一个中介者
public CPU(Mediator mediator) {
super(mediator);
}

public String getVideoData() {
return videoData;
}

public String getSoundData() {
return soundData;
}

//CPU处理数据
public void executeData(String data){
//将一段String以,为标志分开两段
String[] array = data.split(",");
//第一段是影片名称
this.videoData = array[0];
//第二段是声音的数据
this.soundData = array[1];
//通知主板(中介者),CPU完成工作
getMediator().changed(this);
}

}


声卡类

package pers.reus.model.concreteColleague;

import pers.reus.model.colleague.PcComponents;
import pers.reus.model.mediator.Mediator;

public class SoundCard extends PcComponents{
//给声卡设定一个中介者
public SoundCard(Mediator mediator) {
super(mediator);
}

//放出来自CPU的数据
public void soundData(String str){
System.out.println("画外音: " + str);
}
}


影像类

package pers.reus.model.concreteColleague;

import pers.reus.model.colleague.PcComponents;
import pers.reus.model.mediator.Mediator;

public class VideoCard extends PcComponents{
//给影像设定一个中介者
public VideoCard(Mediator mediator) {
super(mediator);

}

//放出来自CPU的数据
public void showData(String str){
System.out.println("影片名称  " + str);
}
}


接下来看中介者——主板: MainBoard的代码展示了从CD驱动开始一直到4个部件全部交互完成的过程,分别是

1.打开CDDriver,CDDriver通知MainBoard完成打开工作



2.MainBoard获取CDDriver数据传给CPU

3.CPU将数据分成2段,CPU通知MainBoard完成分段工作

4.MainBoard获取CPU中被分成2段的数据,传给SoundCard和VideoCard

5.SoundCard 和 VideoCard分别播放

package pers.reus.model.concreteMediator;

import pers.reus.model.colleague.PcComponents;
import pers.reus.model.concreteColleague.CDDriver;
import pers.reus.model.concreteColleague.CPU;
import pers.reus.model.concreteColleague.SoundCard;
import pers.reus.model.concreteColleague.VideoCard;
import pers.reus.model.mediator.Mediator;

public class MainBoard implements Mediator{
//主板必须知道4个需要交互的成员
private CDDriver cdDriver;
private CPU cpu;
private SoundCard soundCard;
private VideoCard videoCard;

/* *
* 因为4个成员也知道主板,
* 也会调用转的changed函数,
* 所以changed函数里还有判断是哪个成员调用了这个函数
* */
public void changed(PcComponents c) {
//判断是否为CD驱动
if (c instanceof CDDriver) {
// 表示CD驱动读取数据了
this.openCDDriverReadData((CDDriver) c);
}//判断是否为CPU
else if (c instanceof CPU) {
// 表示CPU驱动读取数据了
this.openCPU((CPU) c);
}
}
/* *
* CD驱动的特定函数,
* 从CDDriver类知道,
* 在CDDriver通知MainBoard之前,
* 已经先set好了一段data,现在要处理这段data
*  */
public void openCDDriverReadData(CDDriver c){
setCdDriver(c);
String data = cdDriver.getData();
//将来自CDDriver的data交给CPU处理
cpu.executeData(data);
}

//CPU告知MainBoard完成工作后,会调用这个函数
public void openCPU(CPU c){
setCpu(c);
//先获取CPU处理后的数据
String videoData = cpu.getVideoData();
String soundData = cpu.getSoundData();
//把这些数据传递给显卡和声卡展示出来
videoCard.showData(videoData);
soundCard.soundData(soundData);
}

public void setCdDriver(CDDriver cdDriver) {
this.cdDriver = cdDriver;
}

public void setCpu(CPU cpu) {
this.cpu = cpu;
}

public void setSoundCard(SoundCard soundCard) {
this.soundCard = soundCard;
}

public void setVideoCard(VideoCard videoCard) {
this.videoCard = videoCard;
}

}


最后是测试: 调停者模式比较重要一点是,要调停者(中介者)和 被调停者都互相知道对方的存在,所以声明的时候需要如下

package pers.reus.model.client;

import pers.reus.model.concreteColleague.CDDriver;
import pers.reus.model.concreteColleague.CPU;
import pers.reus.model.concreteColleague.SoundCard;
import pers.reus.model.concreteColleague.VideoCard;
import pers.reus.model.concreteMediator.MainBoard;

public class MediatorPatternClient {

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();

}

}


结果:

影片名称:  One Piece
画外音:  海贼王我当定了


这就是将多个需要交互的类的请求集中在一个中介类里面完成的——调停者模式,它的好处的让工作的过程更加清晰地被人了解,不易出错。

ps:这个模式自己学了比较久,其实重点就是上面那句话:将多个需要交互的类的请求集中在一个中介类里面完成。 而代码完完全全是在网上找到,自己也理解很很久,而里面的注释大部分是自己加上去,这样便于大家理解。如果发现错误或者疑惑,欢迎邀请我一起讨论,一起进步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: