定义
用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。
结构和说明
示例代码
public class MediatorDemo {
/**
* 同事类的抽象父类
*/
public static abstract class Colleague {
/**
* 持有中介者对象,每一个同事类都知道它的中介者对象
*/
@Getter
private Mediator mediator;
/**
* 构造方法,传入中介者对象
*
* @param mediator 中介者对象
*/
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
/**
* 具体的同事类
*/
public static class ConcreteColleagueA extends Colleague {
public ConcreteColleagueA(Mediator mediator) {
super(mediator);
}
/**
* 示意方法,执行某些业务功能
*/
public void somOperation() {
// 在需要跟其他同事通信的时候,通知中介者对象
getMediator().changed(this);
}
}
public static class ConcreteColleagueB extends Colleague {
public ConcreteColleagueB(Mediator mediator) {
super(mediator);
}
public void somOperation() {
getMediator().changed(this);
}
}
/**
* 中介者,定义各个同事对象通信的接口
*/
public static interface Mediator {
/**
* 同事对象在自身改变的时候来通知中介者的方法
* 让中介者负责相应的与其他同事对象的交互
*
* @param colleague 同事对象自身,好让中介者对象通过对象实例去获取同事对象的状态
*/
void changed(Colleague colleague);
}
/**
* 具体的中介者实现
*/
public static class ConcreteMediator implements Mediator {
/**
* 持有并维护同事A
*/
@Setter
private ConcreteColleagueA concreteColleagueA;
/**
* 持有并维护同事B
*/
@Setter
private ConcreteColleagueB concreteColleagueB;
@Override
public void changed(Colleague colleague) {
// 某个同事类发生了该改变,通常需要与其他同事交互
// 具体协调相应的同事对象来实现协作行为
}
}
}
调用顺序
广义中介者
- 通常会去掉同事对象的父类,这样可以让任意的对象,只要需要相互交互,就可以成为同事。
- 通常不定义 Mediator 接口,把具体的中介者对象实现成单例。
- 同事对象不再持有中介者,而是在需要的时候直接获取中介对象并调用;中介者也不再持有同事对象,而是在具体处理方法里面去创建,或者从参数传入需要的同事对象。
优缺点
优点
- 松散耦合
中介者模式通过把多个同事对象之间的交互封装到中介者对象里面,从而使得同事对象之间松散耦合,基本上可以做到互不依赖。这样一来,同事对象就可以独立地变化和复用,而不想以前那样“牵一发而动全身”了。
- 集中控制交互
多个同事对象的交互,被封装在中介者对象里面集中管理,使得这些交互行为发生变化的时候,只要修改中介者对象就可以了,当然如果是已经做好的系统,那就扩展中介者对象,而各个同事类不需要做修改。
- 多对多变成一对多
没有使用中介者模式的时候,同事对象之间的关系通常是多对多,引入中介者对象以后,中介者对象和同事对象的关系通常变成了双向的一对多,这会让对象的关系更容易理解和实现。
缺点
- 过度集中化
如果同事对象的交互非常多,并且比较复杂,当这些复杂性全部集中到中介者的时候,会导致中介者对象变得十分复杂,而且难于管理和维护。
思考
本质
封装交互。
何时选用
- 如果一组对象之间的通信比较复杂,导致相互依赖、结构混乱,可以采用中介者模式,把这些对象相互的交互管理起来,各个对象都只需要和中介者交互,从而使得各个对象松散耦合,结构也更清晰易懂。
- 如果一个对象引用很多对象,并且直接跟这些对象交互,导致难以复用该对象,可以采用中介者模式,把这个对象跟其他对象的交互封装到中介者对象里面,这个对象只需要和中介者对象交互就可以了。
相关模式
- 中介者模式和外观模式
这个两个模式有相似的地方,也存在很大的不同。
外观模式多用来封装一个子系统内部的多个模块,目的是向子系统外部提供简单易用的接口。也是就是说外观模式封装的是子系统外部和子系统内部模块间的交互;而中介者模式是提供多个平等的同事对象之间交互关系的封装,一般是用在内部实现上。
另外,外观模式是实现单向的交互,是从子系统外部来调用子系统内部,不回反着来;而中介者模式实现的是内部多个模块间的多向的交互。
- 中介者模式和观察者模式
这两个模式可以组合使用。
中介者模式可以组合使用观察者模式,来实现当同事对象发生改变的时候,通知中介者对象,让中介者对象去进行与其他相关对象的交互。