【设计模式】中介者模式

182 阅读5分钟

本文主要介绍中介者模式的概念和用法。

模式背景

实际开发中,我们存在很多广播性质的需求。比如说当我们发送一个消息,希望很多人同时收到,所以有了QQ群这个功能。有了QQ群,我们就不需要通过自己一个个去发送消息,也就是说这个QQ群帮我和其他的用户进行了解耦。类似于QQ群这样一个引入中间者思想的模式就是中介者模式。

如果不使用中介者模式的话,所有相关的人员全部都耦合在一起的,这种大量的耦合势必有很多缺点。比如:

  1. 很难复用,消息的传播都在消息发送方,如果一个用户也想发送给这个群组,那就又要写一套一样的逻辑代码。
  2. 扩展性差!添加一个成员什么的,就需要修改源代码,违反开闭原则。

定义&概念

中介者模式:使用一个中介对象来封装一系列对象之间的交互,使得各个对象间不需要显式的互相引用,从而减低耦合度。中介者模式又叫调停者模式,是一种对象行为型模式。

原理

系统中有大量的多对多等相互关系,这些关系让系统的类或者组件之间的耦合度就很高,这时候就运用迪米特法则,引入一个中间的类,来维系这些关系,大大降低系统的耦合度。这个引入的中间类就是中介者。

引入了中介者之后,可以让系统中对象的关系由网状结构转为星型结构,如下图所示。系统中的对象交互都通过中介者对象来进行调度。

中介者模式的核心就是这个中介类,他的主要职责:

  1. 中转作用:调用先发送给中介者,中介者转发给需要的接受者。
  2. 协调作用:中介者可以有自己的内部逻辑,将这些逻辑写在中介者类中,也就是说中介者可以辅助调用者做一些操作。

组成要素

  • **抽象中介者:**一个接口,用于各个同事独享之间进行通信。
    • 这是核心,里面有2个核心的部分:
      • 内部持有一个list用来存储转发的对象
      • 提供一个注册方法,可以动态的添加成员。
  • 具体中介者:抽象中介的实现,维持各个同事对象的关系和引用的实现。
  • 抽象同事类:各个同事类的公有方法,申明和中介者通信的抽象方法。
    • 内部持有一个中介者引用,我们还是希望让同事自己能发起调用,相当于将之前其他对象耦合的逻辑抽取到中介者中。
  • 具体同事类:是抽象同事类的子类。每个同事对象需要通信的时候先和中介者通信,间接来和其他同事类通信。

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群这样的广播功能,引入中介者降低耦合。

总结

中介者其实也是我之前提过的,基于代理的思想,只是他们服务的具体细节目标有所不同(但是他们本质都还是代理嘛)。中介者模式多用来处理多对多这种关系复杂的系统,为了让这种关系松耦合才使用的。我们需要一个中介类,因为中介类需要管理一系列的同事类,所以同事类也需要有统一抽象。所以整个中介者模式就是围绕中介类抽象,同事类抽象进行的延伸。

相关代码:github.com/zhaohaoren/…

如有代码和文章问题,还请指正!感谢!