现在的位置: 首页 > 综合 > 正文

设计模式11—设计模式之中介者模式(Mediator)(行为型)

2013年08月18日 ⁄ 综合 ⁄ 共 5774字 ⁄ 字号 评论关闭
文章目录

1.场景问题

电脑中如果没有主板,那么就会出现如下图所示的乱成一团的结构。

 
如果上面的情况发生在软件开发呢?
如果软件开发需要很多模块,难道要每个模块同其他模块各个交互么?那岂不是太不好用么?那么如何简化这种交互呢?跟电脑一样,弄一个中介者就行了。所有的模块跟中介者交互,那么就降低了模块间的耦合性。

2.举一个稍微具体的例子

使用电脑看电影:
首先是光驱读取光盘数据,告诉主板,状态改变
主办得到数据,交给CPU处理
CPU处理完,把数据分为视频和音频,通知主板,它处理完了。
主板去得到CPU处理过后的数据,把数据交给显卡和声卡,然后显示出视频和发出声音。

3.解决方案:中介者模式

3.1中介者定义:

用一个中介对象来封装一系列的对象交互,中介者使得各对象不需要显示的相互引用,从而使其耦合松散,而且可以独立的改变他们之间的交互。这样会有利于对象的修改和维护。

3.2中介者结构图:

 

4.示例代码如下

4.1同事类的抽象父类(注意是个抽象类)

package demo09.mediator.example1;


/**
 * 同事类的抽象父类
 */
public abstract class Colleague {
	/**
	 * 持有中介者对象,每一个同事类都知道它的中介者对象
	 */
	private Mediator mediator;


	/**
	 * 构造方法,传入中介者对象
	 * 
	 * @param mediator
	 *        中介者对象
	 */
	public Colleague(Mediator mediator) {
		this.mediator = mediator;
	}


	/**
	 * 获取当前同事类对应的中介者对象
	 * 
	 * @return 对应的中介者对象
	 */
	public Mediator getMediator() {
		return mediator;
	}
}

4.2同事A注意:是继承奥

package demo09.mediator.example1;
/**
 * 具体的同事类A
 */
public class ConcreteColleagueA extends Colleague {
	public ConcreteColleagueA(Mediator mediator) {
		super(mediator);
	}
	/**
	 * 示意方法,执行某些业务功能
	 */
	public void someOperation() {
		//在需要跟其他同事通信的时候,通知中介者对象
		getMediator().changed(this);
	}
}

4.3同事B注意:是继承

package demo09.mediator.example1;
/**
 * 具体的同事类B
 */
public class ConcreteColleagueB extends Colleague {
	public ConcreteColleagueB(Mediator mediator) {
		super(mediator);
	}
	/**
	 * 示意方法,执行某些业务功能
	 */
	public void someOperation() {
		//在需要跟其他同事通信的时候,通知中介者对象
		getMediator().changed(this);
	}
}

4.4中介者,定义各个同事对象通信的接口

package demo09.mediator.example1;
/**
 * 中介者,定义各个同事对象通信的接口
 */
public interface Mediator {
	/**
	 * 同事对象在自身改变的时候来通知中介者的方法,
	 * 让中介者去负责相应的与其他同事对象的交互
	 * @param colleague 同事对象自身,好让中介者对象通过对象实例
	 *                  去获取同事对象的状态
	 */
	public void changed(Colleague colleague);
}

4.5具体的中介者实现

所有的同事交互都是在中介者中实现

package demo09.mediator.example1;
/**
 * 具体的中介者实现
 */
public class ConcreteMediator implements Mediator {
	
	/**
	 * 持有并维护同事A
	 */
	private ConcreteColleagueA colleagueA;
	/**
	 * 持有并维护同事B
	 */
	private ConcreteColleagueB colleagueB;
	
	/**
	 * 设置中介者需要了解并维护的同事A对象
	 * @param colleague 同事A对象
	 */
	public void setConcreteColleagueA(ConcreteColleagueA colleague) {
		colleagueA = colleague;
	}
	/**
	 * 设置中介者需要了解并维护的同事B对象
	 * @param colleague 同事B对象
	 */
	public void setConcreteColleagueB(ConcreteColleagueB colleague) {
		colleagueB = colleague;
	}
	
	public void changed(Colleague colleague) {
		//某个同事类发生了变化,通常需要与其他同事交户
		//具体协调相应的同事对象来实现协作行为
	}
}

5.使用中介者实现范例:

5.1结构示意图

 

5.2同事类的抽象父类(注意:是个抽象类)

package demo09.mediator.example2;


/**
 * 同事类的抽象父类
 */
public abstract class Colleague {
	/**
	 * 持有中介者对象,每一个同事类都知道它的中介者对象
	 */
	private Mediator mediator;
	/**
	 * 构造方法,传入中介者对象
	 * @param mediator 中介者对象
	 */
	public Colleague(Mediator mediator) {
		this.mediator = mediator;
	}
	/**
	 * 获取当前同事类对应的中介者对象
	 * @return 对应的中介者对象
	 */
	public Mediator getMediator() {
		return mediator;
	}
}

5.3光驱类,一个同事类

package demo09.mediator.example2;
/**
 * 光驱类,一个同事类
 */
public class CDDriver extends Colleague{
	public CDDriver(Mediator mediator) {
		super(mediator);
	}
	/**
	 * 光驱读取出来的数据
	 */
	private String data = "";
	/**
	 * 获取光驱读取出来的数据
	 * @return 光驱读取出来的数据
	 */
	public String getData(){
		return this.data;
	}
	/**
	 * 读取光盘
	 */
	public void readCD(){
		//逗号前是视频显示的数据,逗号后是声音
		this.data = "设计模式,值得好好研究";
		//通知主板,自己的状态发生了改变
		this.getMediator().changed(this);
	}
}

5.4CPU类,一个同事类

package demo09.mediator.example2;
/**
 * CPU类,一个同事类
 */
public class CPU extends Colleague{
	public CPU(Mediator mediator) {
		super(mediator);
	}
	/**
	 * 分解出来的视频数据
	 */
	private String videoData = "";
	/**
	 * 分解出来的声音数据
	 */
	private String soundData = "";
	/**
	 * 获取分解出来的视频数据
	 * @return 分解出来的视频数据
	 */
	public String getVideoData() {
		return videoData;
	}
	/**
	 * 获取分解出来的声音数据
	 * @return 分解出来的声音数据
	 */
	public String getSoundData() {
		return soundData;
	}
	/**
	 * 处理数据,把数据分成音频和视频的数据
	 * @param data 被处理的数据
	 */
	public void executeData(String data){
		//把数据分解开,前面的是视频数据,后面的是音频数据
		String [] ss = data.split(",");
		this.videoData = ss[0];
		this.soundData = ss[1];
		//通知主板,CPU的工作完成
		this.getMediator().changed(this);
	}
}

5.5显卡类,一个同事类

package demo09.mediator.example2;


/**
 * 显卡类,一个同事类
 */
public class VideoCard extends Colleague {
	public VideoCard(Mediator mediator) {
		super(mediator);
	}


	/**
	 * 显示视频数据
	 * 
	 * @param data
	 *        被显示的数据
	 */
	public void showData(String data) {
		System.out.println("您正观看的是:" + data);
	}
}

5.6声卡类,一个同事类

package demo09.mediator.example2;
/**
 * 声卡类,一个同事类
 */
public class SoundCard extends Colleague{
	public SoundCard(Mediator mediator) {
		super(mediator);
	}
	
	/**
	 * 按照声频数据发出声音
	 * @param data 发出声音的数据
	 */
	public void soundData(String data){
		System.out.println("画外音:"+data);
	}
}

5.7中介者接口

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

5.8主板类,实现中介者接口

package demo09.mediator.example2;
/**
 * 主板类,实现中介者接口
 */
public class MotherBoard 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 colleague) {
		if(colleague == cdDriver){
			//表示光驱读取数据了
			this.opeCDDriverReadData((CDDriver)colleague);
		}else if(colleague == cpu){
			//表示CPU处理完了
			this.opeCPU((CPU)colleague);
		}
	}
	/**
	 * 处理光驱读取数据过后与其他对象的交互
	 * @param cd 光驱同事对象
	 */
	private void opeCDDriverReadData(CDDriver cd){
		//1:先获取光驱读取的数据
		String data = cd.getData();
		//2:把这些数据传递给CPU进行处理
		this.cpu.executeData(data);
	}
	/**
	 * 处理CPU处理完数据后与其他对象的交互
	 * @param cpu CPU同事类
	 */
	private void opeCPU(CPU cpu){
		//1:先获取CPU处理过后的数据
		String videoData = cpu.getVideoData();
		String soundData = cpu.getSoundData();
		//2:把这些数据传递给显卡和声卡展示出来
		this.videoCard.showData(videoData);
		this.soundCard.soundData(soundData);
	}
	
}

5.9客户端使用:看电影

package demo09.mediator.example2;


public class Client {
	public static void main(String[] args) {
		// 1:创建中介者——主板对象
		MotherBoard mediator = new MotherBoard();
		// 2:创建同事类
		CDDriver cd = new CDDriver(mediator);
		CPU cpu = new CPU(mediator);
		VideoCard vc = new VideoCard(mediator);
		SoundCard sc = new SoundCard(mediator);
		// 3:让中介者知道所有的同事
		mediator.setCdDriver(cd);
		mediator.setCpu(cpu);
		mediator.setVideoCard(vc);
		mediator.setSoundCard(sc);


		// 4:开始看电影,把光盘放入光驱,光驱开始读盘
		cd.readCD();
	}
}

6.思考中介者模式

6.1中介者模式的功能以及调用顺序图:

封装对象之间的交互。同事之间是如下交互的。

 

6.2中介者模式的本质

封装交互

6.3中介者模式的优缺点

优点:松散耦合,集中控制交互,多对多变成一对多。
缺点:过度集中化,中介者对象变得很复杂,难于管理和维护。

抱歉!评论已关闭.