中介者模式浅析

对于“中介”这个角色,大家在现实生活中也不陌生,比如房产中介。试想一下,如果没有中介这个角色,租房者和房东的关系直接的联系将呈现为网状结构,租房者和房东的关系将是多对多的关系,关系很复杂。当有房产中介的时候,租房者和房东之间将不用在一一的去交互,大家都只要和房产中介这一角色进行交互即可,由中介对象来管理对象的关联关系,避免相互交互的对象之间的紧耦合引用关系。这样,网状结构关系就简化为星型结构关系。如:

同样,在现实生活中的机场飞机起飞和降落,也都是和机场塔台交互,而不是飞机之间的进行交互的。如:

这种用一个中介对象(或者调停者)来封装一系列的对象交互的场景,就是今天要讲的中介者模式所使用的。

一. 中介者模式的基本介绍

意图

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

结构

中介者模式的基本结构如下:

这里涉及到的参与者有如下几种:

  • Mediator(中介者)
    • 中介者定义一个接口用于各同事(Colleague)对象通信。
  • ConcreteMediator(具体中介者)
    • 具体中介者通过协调各同事对象实现协作行为。
    • 了解并维护它的各个同事
  • Colleague(同事类)
    • 每一个同事类都知道它的中介者对象。
    • 每一个同事对象在需与其他的同事通信的时候,与它的中介者通信。

参与者如何协作?

同事向一个中介者对象发送和接收请求。中介者在各同事间适当地转发请求以实现写作行为。

二. 中介者模式的示例

接下来以一个模拟聊天室的简易代码来说明下中介者模式:

  • 抽象同事类

package com.wangmengjun.tutorial.designpattern.mediator;

public abstract class Participant {

  protected String name;

  public abstract void send(String message);

  public abstract void receive(String message, String sender);

  /**
   * @return the name
   */
  public String getName() {
    return name;
  }

  /**
   * @param name the name to set
   */
  public void setName(String name) {
    this.name = name;
  }


}
  • 具体同事类
package com.wangmengjun.tutorial.designpattern.mediator;

public class User extends Participant {

  private Mediator mediator = new ChatRoomMediator();

  public User(String name, Mediator mediator) {
    super();
    this.name = name;
    this.mediator = mediator;
    mediator.addParticipant(this);
  }

  @Override
  public void send(String message) {
    System.out.println(String.format("[%s]发送一条消息 :[%s]", this.getName(),message));
    mediator.sendMessage(message, this);
  }

  @Override
  public void receive(String message, String sender) {
    System.out.println(String.format("[%s]收到一条来自[%s]发送的消息 [%s]", this.getName(),sender,message));
  }

}


  • 中介者
package com.wangmengjun.tutorial.designpattern.mediator;

public interface Mediator {

  void sendMessage(String message, Participant participant);

  void addParticipant(Participant participant);

}
  • 具体中介者

package com.wangmengjun.tutorial.designpattern.mediator;

import java.util.ArrayList;
import java.util.List;

public class ChatRoomMediator implements Mediator{

  private List<Participant> participants = new ArrayList<Participant>();

  @Override
  public void sendMessage(String message, Participant participant) {
    for(Participant p : participants){
      if(p != participant){
        p.receive(message,participant.getName() );
      }
    }
  }

  @Override
  public void addParticipant(Participant participant) {
    participants.add(participant);
  }
}

测试一下:

package com.wangmengjun.tutorial.designpattern.mediator;

public class Main {

  public static void main(String[] args) {
    Mediator chatRoom = new ChatRoomMediator();
    User eric = new User("Eric",chatRoom);
    User lucy = new User("Lucy",chatRoom);
    User lilei  = new User("LiLei",chatRoom);
    User xiaoming  = new User("XiaoMing",chatRoom);

    eric.send("周末一起聚聚啊~~~");
    System.out.println();

    xiaoming.send("好啊");
    System.out.println();

    lilei.send("可以啊");
    System.out.println();

    lucy.send("好啊好啊,啤酒烤串搞起来");
  }
}

输出结果:

[Eric]发送一条消息 :[周末一起聚聚啊~~~]
[Lucy]收到一条来自[Eric]发送的消息 [周末一起聚聚啊~~~]
[LiLei]收到一条来自[Eric]发送的消息 [周末一起聚聚啊~~~]
[XiaoMing]收到一条来自[Eric]发送的消息 [周末一起聚聚啊~~~]

[XiaoMing]发送一条消息 :[好啊]
[Eric]收到一条来自[XiaoMing]发送的消息 [好啊]
[Lucy]收到一条来自[XiaoMing]发送的消息 [好啊]
[LiLei]收到一条来自[XiaoMing]发送的消息 [好啊]

[LiLei]发送一条消息 :[可以啊]
[Eric]收到一条来自[LiLei]发送的消息 [可以啊]
[Lucy]收到一条来自[LiLei]发送的消息 [可以啊]
[XiaoMing]收到一条来自[LiLei]发送的消息 [可以啊]

[Lucy]发送一条消息 :[好啊好啊,啤酒烤串搞起来]
[Eric]收到一条来自[Lucy]发送的消息 [好啊好啊,啤酒烤串搞起来]
[LiLei]收到一条来自[Lucy]发送的消息 [好啊好啊,啤酒烤串搞起来]
[XiaoMing]收到一条来自[Lucy]发送的消息 [好啊好啊,啤酒烤串搞起来]

三. 小结

中介者模式的优缺点:

优点:

(1):减少子类生成。Mediator将原本分布在多个对象间的行为集中在一起。改变这些行为只需生成Mediator的子类即可。这样各个Colleague类可被重用。

(2):它将各个Colleague解耦。Mediator有利于各Colleague间的松耦合,你可以独立的改变和复用各个Colleague类和Mediator类。

(3):中介者模式将多对多的相互作用转化为一对多的相互作用,使得对象之间的关系更加易于维护和理解。

(4):中介者模式将对象的行为和协作抽象化,将中介作为一个独立的概念并将其封装在一个对象中,使你的注意力从对象各自本身的行为转移到它们之间的交互上来。这有助于弄清楚一个系统中的对象是如何交互的。

缺点:

(1):调停者模式降低了同事对象的复杂性,代价是增加了中介者类的复杂性。这可能使得中介者自身成为一个难以维护的庞然大物。

(2):中介者经常充满了各个具体同事类的关系协调代码,这种代码常常是不能复用的。因此,具体同事类的复用是以中介者类的不可复用为代价的。

中介者模式 vs. 门面模式

门面模式和中介者模式很相似,两者均用来给出一个低耦合的系统。门面模式为一个子系统提供一个简单的接口,其中消息的传递是单方向的,因为门面模式的客户端只需要通过门面向子系统发出消息,而不是相反的情况。

中介者模式则不同,它与同事对象的相互作用是多方向的。

中介者模式 vs. 观察者模式

中介者(Mediator)强调的是同事(Colleague)类之间的交互而观察者(Observer)中的目标类(Subject)强调是目标改变后对观察者进行统一的通讯。

观察者模式需要观察者对象和主题对象的相互协作才能达到目的,而且一个观察主题对象通常有几个观察者对象,而一个观察者对象也可以同时观察几个主题对象。

Colleague可以使用观察者模式与Mediator进行交互。

参考

[1]. 阎宏. Java与模式.电子工业出版社

[2]. Erich Gamma. 设计模式-可复用面向对象软件的基础. 机械工业出版社.

本文分享自微信公众号 - 孟君的编程札记(gh_0f0f5e0ae1de),作者:孟君

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Serializable和Externalizable浅析

    Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。从而达到网络传输、本地存储的效果。

    孟君
  • 还在new对象吗?Builder构建对象了解一下?

    在平时开发中,我们经常需要去new一个对象。如果一个类的属性很多,就要设置较多的setXXX,这样实例化和赋值分开,较为分散。

    孟君
  • Lombok,简化代码的神器,你值得拥有

    本文给大家介绍一个Java代码简化的神器 -- Lombok。主要从如下几个方面进行展开:

    孟君
  • SpringBoot统一异常拦截处理

    前言 大家你好! 这是我的第一篇博客 ,我会把我所学所悟的知识以最简单的语言描述清楚,让大家通俗易懂。

    胖虎
  • Java之面向对象例子(二)

    定义一个Book类,在定义一个JavaBook类继承他 //book类 package com.hanqi.maya.model; public class B...

    二十三年蝉
  • 设计模式之中介者模式(行为型)

    中介者模式(Mediator Pattern):中介者模式就是用一个中介对象来封装一系列的对象的交互,使各对象之间不需要显式地相互作用,降低对象之间的耦合度,中...

    SmileNicky
  • 扑克牌例题与Collections工具类

    我们需要创建四个类,一个封装对象的属性,一个封装牌的花色和大小也就是牌的类型,一个实现发牌,排序,洗牌功能,也就是封装对象的行为,最后一个实现图形化界面。

    端碗吹水
  • 使用JAVA反射的利与弊

    我是攻城师
  • 【SpringBoot-3】Lombok使用详解

    Lombak是一款Java开发插件,它主要应用在Java模型对象类中。 Lomabk通过注解的方式,隐式(即代码中不可见,但编译后可见)实现Getter/Se...

    云深i不知处
  • gin框架之请求方法与路由分组

    大话swift

扫码关注云+社区

领取腾讯云代金券