中介者模式

参考

https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/mediator.html

http://c.biancheng.net/view/1393.html

定义

中介者(Mediator)模式的定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。

mediator

应用场景

例如,在 MVC 框架中,控制器(C)就是模型(M)和视图(V)的中介者;还有大家常用的 QQ 聊天程序的“中介者”是 QQ 服务器。所有这些,都可以采用“中介者模式”来实现,它将大大降低对象之间的耦合性,提高系统的灵活性。

  • 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。

  • 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。

  • 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象。

  • 交互的公共行为,如果需要改变行为则可以增加新的中介者类。

实现、应用思路

模式的结构,中介者模式包含以下主要角色:

  1. 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。

  2. 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。

  3. 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。

  4. 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

优点

  1. 简化了对象之间的交互。

  2. 将各同事解耦。

  3. 减少子类生成。

  4. 可以简化各同事类的设计和实现。

缺点

在具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护

代码实例

// 模拟一个聊天室系统

/* 第一版实现,成员有接受和发送方法,每个成员有一个members属性保留着当前与自己在同一个聊天室的成员。
这样就会带来一些问题。
1. 每个成员之间互相引用,关系结构较乱,member对象难以复用。
2. 任何一个对象的变化都需要通知引用了该对象的所有对象进行对应状态更新。
etc... */

/* class Member {
  receive() { }
  send() { }
  members: Member[]
} */

/* 使用中介者模式进行模拟、优化该聊天系统,现在member对象之间的耦合已经解除,对象之间的交互统一通过中介类room来进行,
无需感知其他member对象的存在。我们可以给room类不断扩展来适应新需求,保证member对象的可复用、维护性。*/

// 首先实现中介类room
class Room {
  members: Set<Member>
  constructor() {
    this.members = new Set()
  }
  add(member: Member) {
    this.members.add(member)
    return this
  }
  receive(sender) {
    this.members.forEach(m => sender !== m && m.receive())
  }
}
const room = new Room()

// 实现同事类
class Member {
  name: string
  constructor(name: string) {
    this.name = name
  }
  receive() {
    console.log(`${this.name}收到了消息`)
  }
  send() {
    console.log(`---${this.name}发送了消息---`)
    room.receive(this)
  }
}

const m1 = new Member('m1')
const m2 = new Member('m2')
const m3 = new Member('m3')
room.add(m1).add(m2).add(m3)
m1.send()
m2.send()
上次更新: 5/17/2020, 9:24:33 AM