设计模式-中介者模式
# 七大软件设计原则 # 设计模式-工厂模式 # 设计模式-单例模式 # 设计模式-原型模式 # 设计模式-策略模式 # 设计模式-责任链模式 # 设计模式-建造者模式 # 设计模式-深度分析代理模式 # 设计模式-门面模式 # 设计模式-装饰器模式 # 设计模式-享元模式 # 设计模式-组合模式 # 设计模式-适配器模式 # 设计模式-桥接模式 # 设计模式-委派模式 # 设计模式-模板方法模式 # 设计模式-迭代器模式 # 设计模式-命令模式 # 设计模式-备忘录模式 # 设计模式-状态模式
中介者模式(Mediator Pattern)又称为调解者模式或调停者模式。用一个中介对象封装一 系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立 地改变它们之间的交互。属于行为型模式。
中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使它 们可以松散耦合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作 用。保证这些作用可以彼此独立的变化。其核心思想是,通过中介者解耦系统各层次对象的直 接耦合,层次对象的对外依赖通信统统交由中介者转发。
如下图所示:
在没有使用中介者模式之前各个对象的调用是这样的
使用了中介者模式之后:
从上图可以发现,使用中介者模式之后,任何一个类的变化,只会影响中介者和类本身,不像
之前的设计,任何一个类的变化都会引起其关联所有类的变化。这样的设计大大减少了系统的
耦合度。
中介者模式的适用场景
从上文的解读中我们大致可以总结出一下几种中介者模式的适用场景:
- 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
- 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象
- 交互的公共行为,如果需要改变行为则可以增加新的中介者类
中介者模式的UML类图
具体代码如下:
首先抽象中介者类(也可以不抽象出来直接写具体的中介者):
public abstract class Mediator {
private Colleague colleagueA;
private Colleague colleagueB;
public Colleague getColleagueA() {
return colleagueA;
}
public Colleague getColleagueB() {
return colleagueB;
}
public void register(Colleague colleague){
if(colleague instanceof ConcreteColleagueA){
colleagueA = colleague;
}else{
colleagueB = colleague;
}
}
public abstract void transferA();
public abstract void transferB();
}
具体的中介者:
public class ConcreteMediator extends Mediator{
@Override
public void transferA() {
super.getColleagueA().selfMethod();
}
@Override
public void transferB() {
super.getColleagueB().selfMethod();
}
}
抽象通同事类:
public abstract class Colleague {
protected Mediator mediator;
public abstract void selfMethod();
public abstract void depMethod();
}
具体同事类:
public class ConcreteColleagueA extends Colleague{
public ConcreteColleagueA(Mediator mediator) {
this.mediator = mediator;
this.mediator.register(this);
}
@Override
public void selfMethod() {
System.out.println("ConcreteColleagueA");
}
@Override
public void depMethod() {
this.mediator.transferB();
}
}
public class ConcreteColleagueB extends Colleague{
public ConcreteColleagueB(Mediator mediator) {
this.mediator = mediator;
this.mediator.register(this);
}
@Override
public void selfMethod() {
System.out.println("ConcreteColleagueB");
}
@Override
public void depMethod() {
this.mediator.transferA();
}
}
客户端调用:
public class Test {
public static void main(String[] args) {
Mediator mediator = new ConcreteMediator();
Colleague colleagueA = new ConcreteColleagueA(mediator);
Colleague colleagueB = new ConcreteColleagueB(mediator);
colleagueA.depMethod();
colleagueB.depMethod();
}
}
看到这里可能有些人会觉得像委派模式,的确是有点像的如果仅仅是两个对象的交互基本上和委派差不多了,最大的区别就在于委派是一对一的,而中介者是可以一对多的
还有人会觉得和门面模式很像,确实很像,但是有个最大的区别:中介者模式是让两个类不直接发生关系, 而是通过中介者联系,中介者并不偏向于任一方,双方通过中介者互相和另一方发生关系,关 系是双向的门面模式也是让两个类不直接发生关系,但是门面偏向于某一方,另一方通过门面 和某一方发生关系,但某一方不一定甚至不会通过门面和另一方发生关系,也就是关系偏向于 单向关,门面模式有点类似于创建一个更高级别的对象管理左右对象。
中介者模式在源码中的应用
我们可以看一下Timer源码:
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, period);
}
可以发现的是不管什么方法都会调用sched
方法。我们再看sched
方法的实现
private void sched(TimerTask task, long time, long period) {
if (time < 0)
throw new IllegalArgumentException("Illegal execution time.");
// Constrain value of period sufficiently to prevent numeric
// overflow while still being effectively infinitely large.
if (Math.abs(period) > (Long.MAX_VALUE >> 1))
period >>= 1;
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}
此时我们可以发现,不管什么任务都会被加入到队列中顺序实现,所以此时Timer就变成了中介者对象,而队列中的所有任务的实现对象就是“同事”对象
中介者模式的优缺点
优点:
- 减少类间依赖,将多对多依赖转化成了一对多,降低了类间耦合;
- 类间各司其职,符合迪米特法则。
缺点: 中介者模式中将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。当同事 类越多时,中介者就会越臃肿,变得复杂且难以维护。
转载自:https://juejin.cn/post/7196943016392572988