【设计模式系列 17】中介者模式原理及其在 JDK 源码中的体现
===============================================================
本文主要介绍中介者模式的原理,并会结合示例进行分析。中介者模式其实和桥接有点相似,桥接模式也是通过组合来实现的,但是中介者模式和桥接模式的侧重点不一样,接下来就让我们一起来看看中介者模式吧。
=====================================================================
中介者模式(Mediator Pattern)又称为调节者模式或者调停者模式,是用来降低多个对象和类之间的通信复杂性。
中介者模式中用一个中介对象封装一系列的对象交互,从而使各个对象不需要显示的相互作用,达到松耦合的目的,使得维护更加容易。当某些对象之间的作用发生改变时,不会立刻影响其他的一些对象之间的作用,保证了对象之间的相互作用可以独立的变化。
中介者模式属于行为型模式,其核心思想是通过中介者对象解耦各层次对象的直接耦合,层次对象的对外依赖通信全部交由中介者转发。
=======================================================================
假如现在有六个对象,对象与对象之间都需要互相调用,那么它们的关系就会如下图所示:
各个对象之间互相依赖,整个依赖关系形成了网状,关系错综复杂,非常难以管理。这时候如果引入一个中介者,每个对象都只和中介者交互,那么它们之间的关系就会如下图所示:
可以看到,所有的对象之间的关系都归中介者进行统一管理,避免了各个对象之间各自依赖的乱像。
其实在生活中也一样,比如飞机航线,假如有多驾飞机都需要走同一条航线,那么到底什么时候能走,谁先走就会是一个问题,如果各架飞机之间自己去协商,那么会非常复杂而且容易出错,所以这时候就需要有塔台来统一调度,而塔台扮演的角色就是中介者对象。
====================================================================
好了,装逼时刻又到了:Talk is cheap,Show you the code,先看一个非常简单的例子。
我们就以上面的航空塔台为例子来写一个示例:
1、首先建立一个抽象的 Plane
类,当然这里其实可以不用抽象类,为了方便功能扩展一般我们都是建议面向抽象编程:
package com.lonely.wolf.note.design.pattern.mediator;
public abstract class AbstractPlane {
protected AbstractMediator mediator;
public AbstractPlane(AbstractMediator mediator) {
this.mediator = mediator;
}
public abstract void fly();
}
注意这里面持有了一个抽象中介者对象的引用,稍后我们就会建立中介者对象
2、然后新建两个具体的 PlaneA
和 PlaneB
来继承抽象服务类:
package com.lonely.wolf.note.design.pattern.mediator;
public class PlaneA extends AbstractPlane {
public PlaneA(AbstractMediator mediator) {
super(mediator);
}
@Override
public void fly() {
System.out.println("我是 PlaneA,要过航线,请让道");
super.mediator.notifyPlaneB();
}
public void notifyMe(){
System.out.println("我是 PlaneA,已收到通知,准备让道");
}
}
package com.lonely.wolf.note.design.pattern.mediator;
public class PlaneB extends AbstractPlane {
public PlaneB(AbstractMediator mediator) {
super(mediator);
}
@Override
public void fly() {
System.out.println("我是 PlaneB,要过航线,请让道");
super.mediator.notifyPlaneA();
}
public void notifyMe(){
System.out.println("我是 PlaneB,已收到通知,准备让道");
}
}
注意上面这两个类,重写的抽象方法 fly()
会依赖另一个服务,另外各自有一个接收对方服务的方法 notifyMe()
,如果说我们不使用中介者对象来实现,那么 A
就必须要持有 B
,而 B
又要持有 A
,服务一多,调用关系就会呈现上面的网状形式。而如果有了中介者对象就不一样了,这些服务就可以全部交由中介者来统一管理。
3、建立一个抽象中介者对象:
package com.lonely.wolf.note.design.pattern.mediator;
public abstract class AbstractMediator {
protected Pl
aneA planeA;
protected PlaneB planeB;
public void setPlaneA(PlaneA planeA) {
this.planeA = planeA;
}
public void setPlaneB(PlaneB planeB) {
this.planeB = planeB;
}
public abstract void notifyPlaneA();
public abstract void notifyPlaneB();
}
4、再建立一个具体的中介者对象塔台:
package com.lonely.wolf.note.design.pattern.mediator;
public class ControlTower extends AbstractMediator{
@Override
public void notifyPlaneA() {
super.planeA.notifyMe();
}
@Override
public void notifyPlaneB() {
super.planeB.notifyMe();
}
}
5、最后我们建立一个测试类来测试一下:
package com.lonely.wolf.note.design.pattern.mediator;
public class TestMediator {
public static void main(String[] args) {
AbstractMediator controlTower = new ControlTower();
PlaneA planeA = new PlaneA(controlTower);
PlaneB planeB = new PlaneB(controlTower);
controlTower.setPlaneA(planeA);
controlTower.setPlaneB(planeB);
planeA.fly();
System.out.println("--------------------");
planeB.fly();
}
}
输出结果如下:
我是 PlaneA,要过航线,请让道
我是 PlaneB,已收到通知,准备让道
我是 PlaneB,要过航线,请让道
我是 PlaneA,已收到通知,准备让道
可以看到,在这个例子中我们实现了 PlaneA
和 PlaneB
的互相调用,但是相互都不持有对方的引用,而是通过一个中介者对象来统一管理,如果后续需要新增其他服务的调用,那么只需要改变中介者对象就可以了。
====================================================================
从上面示例中,我们可以得出中介者模式主要有 4 个角色:
抽象中介者(Mediator):定义一个抽象角色,用于各个同事角色之间的通信(如示例中的 AbstractMediator)。
具体中介者(ConcreteMediator):从具体同事的对象接收消息,并像具体同事对象发出命令,用来协调各个同事对象之间通信协作(如示例中的
ControlTower
)。抽象同事类(Colleague):每一个同事对象均需要依赖中介者角色,所以一般将中介者角色集成到该角色之中,与其他同事在通信时,通过中介者角色进行转发(如示例中的
AbstractPlane
)。具体同事类(ConcreteColleague):负责实现自发行为(Self-Method),转发依赖方法(Dep-Method)交由中介者进行协调处理(如示例中的
PlaneA
和PlaneB
,自发行为就是方法notifyMe()
方法,转发行为对应fly()
方法)。
==========================================================================
评论