设计模式--中介者模式(Mediator)

 本文是设计模式学习笔记的第三篇文章,主要分析的是中介者模式。是清华大学出版社的《研读设计模式》的读书笔记。在此感谢原作者。



这次应用的是一个实例去理解中介者模式


先来看这样一个实例,电脑播放电影。


我们需要一个DVD,然后放入播放器中,播放器获得数据传递给CPU处理在将数据传给显卡和声卡,循环这个流程。简单么?

实际上,如果没有主板,各部件要自行交互的话是非常复杂的,而且各个配件的接口不同,还要进行转化才能匹配,这是多么烦躁的事情。

所以,我们的电脑上会有主板,每个配件只需要做自己的本职工作就好,做好的东西给主板,需要的东西从主板拿。主板就是一个中介者。


在软件开发上,其实就是解耦。如果每个类都需要和其他类进行交互,那么当一个类发生改变的时候,其他类也要改变,我们可不希望这样。


让我们看看应用中介者模式模拟的电脑播放电影的过程。体验下中介者所干的事情。



先准备好CD,在工程下建立一个a.txt文件,内容如下:

READY?GO!,碾碎他们
~\(≧▽≦)/~,啦啦啦德玛西亚
~\(≧▽≦)/~~\(≧▽≦)/~,啦啦啦啦德玛西亚
~\(≧▽≦)/~~\(≧▽≦)/~~\(≧▽≦)/~,德玛德玛德玛西亚
  ╭︿︿︿╮     ,{/ o  o /}
 ( (oo) )  , ︶ ︶︶    
>>>>FIRST BLOOD<<<<,FIRST BLOOD


首先是CD类:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class CD {

	//设定cd
	private String filePath = null;
	
	private File myFile = null;
	
	public File getFile(){
		return myFile;
	}
	
	public CD(String filePath){
		this.filePath = filePath;
		myFile = new File(filePath);
	}
	
}



然后是中介者接口:


public interface Mediator {

	/**
	 * 同时对象在自身改变的时候来通知中介者的方法
	 * 让中介者去负责相应的与其他同时对象的交互
	 * @param colleague 同时对象自身,好让中介者对象通过对象实例
	 *                  去获取同时对象的状态
	 */
	public void changed(Colleague colleague);
}



然后是实现中介者接口的主板类:


public class MotherBoard implements Mediator{

	private CDDriver cdDriver = null;
	
	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 colleague){
		if(colleague == cdDriver){
			//表示光驱读取数据了
			this.opeCDDriverReadData((CDDriver)colleague);
		}else if (colleague == cpu) {
			//表示CPU处理完了
			this.opeCPU((CPU)colleague);
		}
	}
	
	/**
	 * 处理光驱读取数据后与其他对象的交互
	 * @param cdDriver 光驱对象
	 */
	public void opeCDDriverReadData(CDDriver cdDriver){
		//1:先获取光驱读取的数据
		String data = cdDriver.getData();
		//2:把这些数据传递给CPU进行处理
		this.cpu.executeData(data);
	}
	
	public void opeCPU(CPU cpu){
		//获取CPU处理后的数据
		String videoData = cpu.getVideoData();
		String soundData = cpu.getSoundData();
		//把这些数据传递给显卡和声卡
		this.videoCard.showData(videoData);
		this.soundCard.soundData(soundData);
	}

}



然后是同事(部件)的父类(抽象类):

public abstract class Colleague {

	private Mediator mediator;
	
	public Colleague(Mediator mediator){
		this.mediator = mediator;
	}
	
	public  Mediator getMediator() {
		return mediator;
	}
}


然后是部件CDDriver类:


import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * 光驱类,一个同事类
 * 
 * @author qian.xu
 * 
 */
public class CDDriver extends Colleague {

	public CDDriver(Mediator mediator) {
		super(mediator);
		// TODO Auto-generated constructor stub
	}

	/**
	 * 光驱读出来的数据
	 */
	private String data = "";

	/**
	 * 光驱读取出来的数据
	 * 
	 * @return 光驱读取出来的数据
	 */
	public String getData() {
		return this.data;
	}

	/**
	 * 读取光驱
	 */
	public void readCD(CD cd) {

		try {

			File file = cd.getFile();
			FileReader reader = new FileReader(file);
			BufferedReader br = new BufferedReader(reader);
			while ((data = br.readLine()) != null) {
				this.getMediator().changed(this);
				Thread.sleep(3000);
			}

			br.close();
			reader.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}




然后是部件CPU类:


/**
 * COU,一个同事类
 * @author qian.xu
 *
 */
public class CPU extends Colleague{

	public CPU(Mediator mediator) {
		super(mediator);
		// TODO Auto-generated constructor stub
	}

	/**
	 * 分解出来的视频数据
	 */
	private String videoData = "";
	/**
	 * 分解出来的音频数据
	 */
	private String soundData = "";
	
	/**
	 * 获取分解出来的视频数据
	 * @return 分解出来的视频数据
	 */
	public String getVideoData(){
		return videoData;
	}
	
	/**
	 * 获取分解出来的音频数据
	 * @return 分解出来的音频数据
	 */
	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);
	}
}



然后是部件显卡类:


/**
 * 显卡类,一个同事类
 * @author qian.xu
 *
 */
public class VideoCard extends Colleague{

	public VideoCard(Mediator mediator) {
		super(mediator);
		// TODO Auto-generated constructor stub
	}
	
	
	/**
	 * 显示视频数据
	 * @param data 被显示的数据
	 */
	public void showData(String data){
		System.out.println("视频流:"+data);
	}
}




最后是部件声卡类:


public class SoundCard extends Colleague{

	public SoundCard(Mediator mediator) {
		super(mediator);
		// TODO Auto-generated constructor stub
	}
	
	
	/**
	 * 声卡工作
	 * @param data 要发出的声音
	 */
	public void soundData(String data){
		System.out.println("音频流:"+data);
	}

}



终于完事了,让我们打开播放器开电影吧,下面是测试类:


public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//创造主板
		MotherBoard mediator = new MotherBoard();
		//创建各部件
		CD cd = new CD("a.txt");
		CDDriver cdDriver = new CDDriver(mediator);
		CPU cpu = new CPU(mediator);
		VideoCard videoCard = new VideoCard(mediator);
		SoundCard soundCard = new SoundCard(mediator);
		
		//组装各部件到主板上	
		mediator.setCdDriver(cdDriver);
		mediator.setCpu(cpu);
		mediator.setVideoCard(videoCard);
		mediator.setSoundCard(soundCard);
		//将CD放入播放器中
		cdDriver.readCD(cd);

	}




输出结果(为了模仿的更像,加入了线程睡眠,有了延迟输出的效果,所有建议将程序跑起来看下):


视频流:READY?GO!
音频流:碾碎他们
视频流:~\(≧▽≦)/~
音频流:啦啦啦德玛西亚
视频流:~\(≧▽≦)/~~\(≧▽≦)/~
音频流:啦啦啦啦德玛西亚
视频流:~\(≧▽≦)/~~\(≧▽≦)/~~\(≧▽≦)/~
音频流:德玛德玛德玛西亚
视频流:  ╭︿︿︿╮     
音频流:    {/ o  o /}
视频流:     ( (oo) )  
音频流:     ︶ ︶︶    
视频流:>>>>FIRST BLOOD<<<<
音频流:FIRST BLOOD







中介者的本质

中介者的本质是封装交互。中介者的目的,就是用来封装多个对象的交互,这些交互的处理多在中介者对象里面实现。因此中介对象的复杂程度,取决于他封装的交互的复杂程度。


何时选用中介者模式

建议在以下情况时选用中介者模式。

★  如果一组对象之间的通信方式比较复杂,导致相互依赖、结构混乱。可以采用中介者模式,把这些对象的交互管理起来,各个对象都只需要和中介者交互,从而使得各个对象松散耦合,结构也更清晰易懂。

★ 如果一个对象引用很多的对象,并直接跟这些对些对象交互,导致难以复用该对象,可以采用中介者模式,把这个对象跟其他对象的交互封装到中介者对象里边,这个对象只需要和中介者对象交互就好了。


中介者模式的不足

中介者模式的一个潜在缺点是,过度集中化。如果同事对象的交互非常多,而且比较复杂,当这些复杂性全部集中到中介者的时候,会导致中介者对象变得十分复杂,难于管理和维护。


广义中介者

在应用开发中,经常会简化中介者模式,来使开发变得简单,比如:

★通常会去掉同事对象的父类,这样可以让任意的对象,只需要相互交互,就可以成为同事。

★通常不定义Mediator接口,把具体的中介者对象实现为单例。

★同事对象不再持有中介者,而是在需要的时候直接获取中介者对象并调用,对应的,中介者也不再持有对象同事,而是在具体的处理方法里去创建,或者读取。





  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值