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

调停者/中介者模式:

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:这个模式自己学了比较久,其实重点就是上面那句话:将多个需要交互的类的请求集中在一个中介类里面完成。  而代码完完全全是在网上找到,自己也理解很很久,而里面的注释大部分是自己加上去,这样便于大家理解。如果发现错误或者疑惑,欢迎邀请我一起讨论,一起进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值