`

中介者模式(mediator)

阅读更多
电脑的各个配件之间的交互,都是通过主板完成的,如果没有主板,各个配件就必须自行相互交互。类似的,将配件都抽象成为一个类或者是子系统,那就相当于出现了多个类之间相互交互,而且交互很繁琐,类与类就耦合了,是不是很麻烦?
如何简化这种多个对象之间的交互呢?

为了演示,考虑具体点的功能,使用电脑来看电影,将这个过程描述出来。交互过程如下:
(1)首先光驱读取光盘上的数据,然后告诉主板,它的状态改变了
(2)主板去得到光驱的数据,把这些数据交给cpu进行分析处理
(3)cpu处理完后,把数据分成了视频和音频数据,通知主板,处理完了
(4)主板得到cpu处理过后的数据,分别把数据交给显卡和声卡,去显示出视频和音频
如何实现这个过程??----------》中介者模式

定义:用一个中介对象来封装一系列的对象交互。中介者使得各个对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。
让各个对象只和中介者交互,而中介者知道如何和其他所有对象进行交互。
有了中介者后,所有的交互都封装到中介者对象里面了。其他对象,被视为同事类。
中介者模式的结构:
Mediator:中介者接口,定义同事类之间的交互需要的方法
ConcreteMediator:具体中介者实现对象。需要了解并维护各个同事对象,并负责具体协调各个同事对象的交互关系
Colleague:同事类的定义,通常实现为抽象类,主要约束同事对象的类型,并定义一些具体同事类之间的公共功能,比如具体同事类都会持有中介者对象,都可以定义在这个类里面。
ConcreteColleague:具体同事类,实现自己的业务,在需要与其他同事类进行通信时,就与持有的中介者进行通信。所有的同事类都要持有中介者。
package mediator;
//中介者,定义各个同事通信的接口
public interface Mediator {

//	同事类在自身改变时,通知中介者
	public void changed(Colleague colleague);

}


package mediator;
//具体中介者
public class ConcreteMediator implements Mediator {
	
	private ConcreteColleagueA colleagueA; //持有并维护同事A
	private ConcreteColleagueB colleagueB;//持有并维护同事B

	@Override
	public void changed(Colleague colleague) {

		//某个同事类发生了变化,通常需要与其他同事交互
		//具体协调相应的同事对象来实现协作行为
		
	}

	public void setColleagueA(ConcreteColleagueA colleagueA) {
		this.colleagueA = colleagueA;
	}

	public void setColleagueB(ConcreteColleagueB colleagueB) {
		this.colleagueB = colleagueB;
	}

}


package mediator;
//同事类的抽象父类
public abstract class Colleague {

	private Mediator mediator; //持有的中介者对象

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

	public Mediator getMediator() {
		return mediator;
	}
	
}


package mediator;
//具体的同事类
public class ConcreteColleagueA extends Colleague {

	public ConcreteColleagueA(Mediator mediator) {
		super(mediator);
	}

//	示意方法,执行某些业务
	public void someOperation(){
//		在需要与其他同事通信时,通知中介者对象
		this.getMediator().changed(this);
	}
}

同事B的代码类似
主板相当于中介者,而光驱,cpu,声卡,显卡等配件为同事对象
package mediatorSolve;
//中介者,定义各个同事通信的接口
public interface Mediator {

//	同事类在自身改变时,通知中介者
	public void changed(Colleague colleague);

}


package mediatorSolve;

//实现中介者的具体对象,这里是主板类
public class MotherBoard implements Mediator {

	// 需要知道光驱,声卡,显卡和cpu对象
	private CPU cpu;
	private VideoCard videoCard;
	private SoundCard soundCard;

	private CDDriver driver;


	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 setDriver(CDDriver driver) {
		this.driver = driver;
	}

	@Override
	public void changed(Colleague colleague) {

		if (colleague == driver) {
			// 表示光驱已经读取数据了
			this.opeCDDriverReadData((CDDriver) colleague);
		}

		else if (colleague == cpu) {
			// 表示cpu处理完了
			this.opeCPU((CPU) colleague);
		}

	}

	// 处理cpu处理完数据后与声卡和显卡的交互
	private void opeCPU(CPU colleague) {
//		先获取cpu处理后的数据
		String videoData = colleague.getVideoData();
		String soundData = colleague.getSoundData();
//     将数据传递给显卡和声卡展示出来
		videoCard.showData(videoData);
		soundCard.showData(soundData);
	}

	// 处理光驱读取数据以后与其他对象的交互
	private void opeCDDriverReadData(CDDriver colleague) {

		// 1:先获取光驱读取的数据
		String data = colleague.getData();
		// 2:把这些数据传递给CPU进行处理
		cpu.executeData(data);
	}

}


package mediatorSolve;
//同事类的抽象父类
public abstract class Colleague {

	private Mediator mediator; //持有的中介者对象

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

	public Mediator getMediator() {
		return mediator;
	}
	
}


package mediatorSolve;

public class CPU extends Colleague {
	
	private String videoData = ""; //分离出来的视频数据
	private String soundData = ""; //分离出来的音频数据

	public CPU(Mediator mediator) {
		super(mediator);
	}
	
	public void executeData(String data){
//		处理数据,将数据分为音频和视频数据
		String[] ss = data.split(",");
		this.videoData = ss[0];
		this.soundData = ss[1];
		
		//通知主板,cpu的工作完成
		this.getMediator().changed(this);
	}

	public String getVideoData() {
		return videoData;
	}

	public String getSoundData() {
		return soundData;
	}
	}


package mediatorSolve;
//光驱类
public class CDDriver extends Colleague {

	private String data = ""; // 光驱读取的数据
	public CDDriver(Mediator mediator) {
		super(mediator);
	}
	public String getData() { //获取光驱读取的数据
		return data;
	}

	public void readCD(){
//		读取光盘
		//逗号前是视频显示的数据,逗号后是声音
		this.data = "设计模式,值得好好研究";
		//通知主板,自己的状态发生了改变
		this.getMediator().changed(this);
	}
	
}

package mediatorSolve;

public class SoundCard extends Colleague {

	public SoundCard(Mediator mediator) {
		super(mediator);
	}
	
	public void showData(String data){
		System.out.println("画外音:"+data);
	}
}

package mediatorSolve;

public class VideoCard extends Colleague {

	public VideoCard(Mediator mediator) {
		super(mediator);
	}
	
	public void showData(String data){
		System.out.println("您正在观看的是:"+data);
	}

}


package mediatorSolve;

public class Client {

public static void main(String[] args) {

//创建中介者,主板对象
MotherBoard mb = new MotherBoard();
//创建同事类
CDDriver driver = new CDDriver(mb);
VideoCard video = new VideoCard(mb);
SoundCard sound = new SoundCard(mb);
CPU cpu = new CPU(mb);

//让中介者知道所有的同事
mb.setCpu(cpu);
mb.setDriver(driver);
mb.setSoundCard(sound);
mb.setVideoCard(video);

driver.readCD();
// 无需下面这些操作,中介者就协调执行了这些操作
// cpu.executeData(driver.getData());
// video.showData(cpu.getVideoData());
// sound.showData(cpu.getSoundData());
}
}


中介者模式中,要求这些类都有继承相同的类。
在实际应用中,经常会简化中介者模式,来使开发变得简单,比如如下的简化:
(1)去掉同事对象的父类,这样可以让任意的对象,只要需要相互交互,就可以成为同事
(2)不定义Mediator接口,把具体的中介者对象实现为单例
(3)同事对象不再持有中介者,而是需要时直接获取中介者对象并调用,中介者也不再持有同事对象,而是在具体处理方法中去创建,获取获取。
简化后的称为广义中介者。
考虑以下实际应用:部门和人员(多对多关系)
使用广义的中介者模式来管理部门和人员之间的关系,如部门合并,人员离职,调职等,如包generalMediator中示例
中介者模式优点:松散耦合,集中控制交互,多对多变为一对多。
缺点:过度集中化,如果同事间交互比较复杂,中介者就会变得非常复杂
本质:封装交互
如果一组对象之间的通信方式比较复杂,导致相互依赖、结构混乱,可采用中介者模式。如果一个对象引用很多对象,并直接与这些对象交互,也可使用中介者模式
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics