本文主要介绍中介者模式的概念和用法。
模式背景
实际开发中,我们存在很多广播性质的需求。比如说当我们发送一个消息,希望很多人同时收到,所以有了QQ群这个功能。有了QQ群,我们就不需要通过自己一个个去发送消息,也就是说这个QQ群帮我和其他的用户进行了解耦。类似于QQ群这样一个引入中间者思想的模式就是中介者模式。
如果不使用中介者模式的话,所有相关的人员全部都耦合在一起的,这种大量的耦合势必有很多缺点。比如:
- 很难复用,消息的传播都在消息发送方,如果一个用户也想发送给这个群组,那就又要写一套一样的逻辑代码。
- 扩展性差!添加一个成员什么的,就需要修改源代码,违反开闭原则。
定义&概念
中介者模式:使用一个中介对象来封装一系列对象之间的交互,使得各个对象间不需要显式的互相引用,从而减低耦合度。中介者模式又叫调停者模式,是一种对象行为型模式。
原理
系统中有大量的多对多等相互关系,这些关系让系统的类或者组件之间的耦合度就很高,这时候就运用迪米特法则,引入一个中间的类,来维系这些关系,大大降低系统的耦合度。这个引入的中间类就是中介者。
引入了中介者之后,可以让系统中对象的关系由网状结构转为星型结构,如下图所示。系统中的对象交互都通过中介者对象来进行调度。
中介者模式的核心就是这个中介类,他的主要职责:
- 中转作用:调用先发送给中介者,中介者转发给需要的接受者。
- 协调作用:中介者可以有自己的内部逻辑,将这些逻辑写在中介者类中,也就是说中介者可以辅助调用者做一些操作。
组成要素
- **抽象中介者:**一个接口,用于各个同事独享之间进行通信。
- 这是核心,里面有2个核心的部分:
- 内部持有一个list用来存储转发的对象
- 提供一个注册方法,可以动态的添加成员。
- 这是核心,里面有2个核心的部分:
- 具体中介者:抽象中介的实现,维持各个同事对象的关系和引用的实现。
- 抽象同事类:各个同事类的公有方法,申明和中介者通信的抽象方法。
- 内部持有一个中介者引用,我们还是希望让同事自己能发起调用,相当于将之前其他对象耦合的逻辑抽取到中介者中。
- 具体同事类:是抽象同事类的子类。每个同事对象需要通信的时候先和中介者通信,间接来和其他同事类通信。
UML
实现
抽象中介者
public abstract class Mediator {
/**
* 维系着同事对象的引用
*/
protected ArrayList<Colleague> colleagues = new ArrayList<>();
/**
* 往中介者中添加同事对象
*/
public void register(Colleague colleague) {
colleagues.add(colleague);
}
/**
* 中介的关系逻辑
*/
public abstract void operation(Colleague colleague);
}
具体中介者
public class ConcreteMediator extends Mediator {
@Override
public void operation(Colleague colleague) {
//这里将注册的同事类的关系联系起来
//这里只是瞎写了一个逻辑。
if (colleague == colleagues.get(0)) {
colleague.op();
colleagues.get(1).op();
} else {
colleagues.get(1).op();
colleague.op();
}
}
}
抽象同事类
public abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
/**
* 同事自己的方法,一般也是其他同事所耦合的向要调用的方法。
*/
public abstract void op();
/**
* 自己定义依赖方法,与中介者进行通信
*/
public void send() {
mediator.operation(this);
}
}
具体同事类
public class ColleagueX extends Colleague{
public Colleague1(Mediator mediator) {
super(mediator);
}
@Override
public void op() {
System.out.println("i am X");
}
}
使用
//定义中介者
ConcreteMediator concreteMediator = new ConcreteMediator();
//定义同事
Colleague1 colleague1 = new Colleague1(concreteMediator);
Colleague2 colleague2 = new Colleague2(concreteMediator);
//同事注册到中介者上
concreteMediator.register(colleague1);
concreteMediator.register(colleague2);
//触发改动
colleague1.send();
colleague2.send();
优缺点
优点
- 降低了类的复杂度,将多对多转化成了一对多,更方便理解类对象之间的关系。
- 对相互交互的类进行了解耦。
- 可复用,一个中介者可以说是一个群组,这个群组可以被多个
- 符合迪米特原则。
缺点
- 如果各个同事间的交互非常多并且复杂情况下,中介者可能会变得十分复杂,不易维护和管理。
使用场景
系统中对象之间存在复杂的引用关系,让系统看着很复杂,可以使用中介者来清理交互的脉络。或者就如需要实现QQ群这样的广播功能,引入中介者降低耦合。
总结
中介者其实也是我之前提过的,基于代理的思想,只是他们服务的具体细节目标有所不同(但是他们本质都还是代理嘛)。中介者模式多用来处理多对多这种关系复杂的系统,为了让这种关系松耦合才使用的。我们需要一个中介类,因为中介类需要管理一系列的同事类,所以同事类也需要有统一抽象。所以整个中介者模式就是围绕中介类抽象,同事类抽象进行的延伸。
附
如有代码和文章问题,还请指正!感谢!