初识中介者模式
定义
用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显式
地相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互。
结构和说明
- Mediator:
中介者接口。在里面定义各个同事之间交互需要的方法,可以是公共的通
讯方法,比如changed方法,大家都用,也可以是小范围的交互方法。
- ConcreteMediator:
具体中介者实现对象。它需要了解并维护各个同事对象,并负责具体的协
调各同事对象的交互关系。
- Colleague:
同事类的定义,通常实现成为抽象类,主要负责约束同事对象的类型,并
实现一些具体同事类之间的公共功能,比如:每个具体同事类都应该知道中介者
对象,也就是具体同事类都会持有中介者对象,就可以定义到这个类里面。
- ConcreteColleague:
具体的同事类,实现自己的业务,在需要与其它同事通讯的时候,就与持
有的中介者通信,中介者会负责与其它的同事交互。
示例代码
同事类的抽象父类
package cn.javass.dp.mediator.example1;
/**
* 同事类的抽象父类
*/
public abstract class Colleague {
/**
* 持有中介者对象,每一个同事类都知道它的中介者对象
*/
private Mediator mediator;
/**
* 构造方法,传入中介者对象
* @param mediator 中介者对象
*/
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
/**
* 获取当前同事类对应的中介者对象
* @return 对应的中介者对象
*/
public Mediator getMediator() {
return mediator;
}
}
具体的同事类A
package cn.javass.dp.mediator.example1;
/**
* 具体的同事类A
*/
public class ConcreteColleagueA extends Colleague {
public ConcreteColleagueA(Mediator mediator) {
super(mediator);
}
/**
* 示意方法,执行某些业务功能
*/
public void someOperation() {
//在需要跟其他同事通信的时候,通知中介者对象
getMediator().changed(this);
}
}
具体的同事类B
package cn.javass.dp.mediator.example1;
/**
* 具体的同事类B
*/
public class ConcreteColleagueB extends Colleague {
public ConcreteColleagueB(Mediator mediator) {
super(mediator);
}
/**
* 示意方法,执行某些业务功能
*/
public void someOperation() {
//在需要跟其他同事通信的时候,通知中介者对象
getMediator().changed(this);
}
}
中介者,定义各个同事对象通信的接口
package cn.javass.dp.mediator.example1;
/**
* 中介者,定义各个同事对象通信的接口
*/
public interface Mediator {
/**
* 同事对象在自身改变的时候来通知中介者的方法,
* 让中介者去负责相应的与其他同事对象的交互
* @param colleague 同事对象自身,好让中介者对象通过对象实例
* 去获取同事对象的状态
*/
public void changed(Colleague colleague);
}
具体的中介者实现
package cn.javass.dp.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) {
//某个同事类发生了变化,通常需要与其他同事交互
//具体协调相应的同事对象来实现协作行为
}
}
体会中介者模式
如果没有主板
如果电脑里面没有了主板,那么各个配件之间就必须自行相互交互,以互
相传送数据,理论上说,基本上各个配件相互之间都存在交互数据的可能
有了主板,各个配件的交互完全通过主板来完成,每个配件都只需要和主
板交互,而主板知道如何和所有的配件打交道,那就简单多了
存在的问题
如果上面的情况发生在软件开发上呢?
如果把每个电脑配件都抽象成为一个类或者是子系统,那就相当于出现了
多个类之间相互交互,而且交互还很繁琐,导致每个类都必须知道所有需要交互
的类,也就是我们常说的类和类耦合了,是不是很麻烦?
这样一来,不但开发的时候每个类会复杂,因为要兼顾其它的类,更要命
的是每个类在发生改动的时候,需要通知所有相关的类一起修改,因为接口或者
是功能发生了变动,使用它的地方都得变,太可怕了吧!
那该如何来简化这种多个对象之间的交互呢?
使用电脑来看电影
为了演示,考虑一个稍微具体点的功能。在日常生活中,我们经常使用电
脑来看电影,把这个过程描述出来,这里仅仅考虑正常的情况,也就是有主板的
情况,简化后假定会有如下的交互过程:
- 1:首先是光驱要读取光盘上的数据,然后告诉主板,它的状态改变了
- 2:主板去得到光驱的数据,把这些数据交给CPU进行分析处理
- 3:CPU处理完后,把数据分成了视频数据和音频数据,通知主板,它处理完了
- 4:主板去得到CPU处理过后的数据,分别把数据交给显卡和声卡,去显示出视频和
发出声音
当然这是一个持续的、不断重复的过程,从而形成不间断的视频和声音,
具体的运行过程不在讨论之列,假设就有如上简单的交互关系就可以了。也就是
说想看电影,把光盘放入光驱,光驱开始读盘,就可以看电影了
使用模式的解决方案
示例代码
同事类的抽象父类
package cn.javass.dp.mediator.example2;
/**
* 同事类的抽象父类
*/
public abstract class Colleague {
/**
* 持有中介者对象,每一个同事类都知道它的中介者对象
*/
private Mediator mediator;
/**
* 构造方法,传