【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:这个模式自己学了比较久,其实重点就是上面那句话:将多个需要交互的类的请求集中在一个中介类里面完成。 而代码完完全全是在网上找到,自己也理解很很久,而里面的注释大部分是自己加上去,这样便于大家理解。如果发现错误或者疑惑,欢迎邀请我一起讨论,一起进步。
相关文章推荐
- eclipse 插件relo使用
- 向eclipse中导入myeclipse项目
- eclipse下使用动态库、静态库相应的配置
- 使用Android design support library在Eclipse和Android Studio
- Java获取资源路径
- java-为什么配置环境变量
- Java 堆排序 Top K
- 如何调节Eclipse下console输出字体的大小
- Java 二分法查找
- Java 快速排序 快排
- java计算当前周开始日期&结束日期
- mybatis与spring3.1整合----
- java线程研究---(4)暂停Thread:sleep
- java多线程实现
- Hadoop2.x eclipse下编程环境配置
- 使用MyEclipse开发第一个Web程序
- 【JNI】Java调用C函数
- cmd安装weblogic12c的时候总是说jre不是有效的JDK
- 防止表单的重复提交
- java程序的换行符/n怎么写?