定义

用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。

模式结构

中介者模式包含如下角色:

  • 抽象中介者(Mediator):中介者定义一个接口用于与各同事(Colleague)对象通信。
  • 具体中介者(ConcreteMediator): 具体中介者通过协调各同事对象实现协作行为。了解并维护它的各个同事。
  • 抽象同事类(Colleague): 定义同事类接口,定义各同事的公有方法.
  • 具体同事类(ConcreteColleague): 实现抽象同事类中的方法。每一个同时类需要知道中介者对象;每个具体同事类只需要了解自己的行为,而不需要了解其他同事类的情况。每一个同事对象在需与其他的同事通信的时候,与它的中介者通信。

image.png 中介者模式(Mediator) - 图2

代码分析

Mediator类

  1. /// 抽象中介者类
  2. class Mediator: NSObject {
  3. func send(message: String, colleague:Colleague) {
  4. }
  5. }

ConcreteMediator类

  1. /// 具体中介者
  2. class ConcreteMediator: Mediator {
  3. var colleagueA: ConcreteColleagueA? = nil
  4. var colleagueB: ConcreteColleagueB? = nil
  5. /// 消息发送
  6. ///
  7. /// - Parameters:
  8. /// - message: 要发送的消息
  9. /// - colleague: 发送者对象(发出消息的一方)
  10. override func send(message: String, colleague: Colleague) {
  11. if colleague == colleagueA {
  12. colleagueB?.notify(message: message)
  13. } else {
  14. colleagueA?.notify(message: message)
  15. }
  16. }
  17. }


Colleague类

  1. /// 抽象同事类
  2. class Colleague: NSObject {
  3. var mediator :Mediator
  4. init(mediator: Mediator) {//得到中介者对象
  5. self.mediator = mediator
  6. }
  7. }

ConcreteColleagueA类

  1. class ConcreteColleagueA: Colleague {
  2. func send(message: String) {
  3. mediator.send(message: message, colleague: self)
  4. }
  5. func notify(message: String) {
  6. print("同事A得到消息:\(message)")
  7. }
  8. }

ConcreteColleagueB类

  1. class ConcreteColleagueB: Colleague {
  2. func send(message: String) {
  3. mediator.send(message: message, colleague: self)
  4. }
  5. func notify(message: String) {
  6. print("同事B得到消息:\(message)")
  7. }
  8. }

调用

  1. let mediator: ConcreteMediator = ConcreteMediator()
  2. let a: ConcreteColleagueA = ConcreteColleagueA(mediator: mediator)
  3. let b: ConcreteColleagueB = ConcreteColleagueB(mediator: mediator)
  4. mediator.colleagueA = a
  5. mediator.colleagueB = b
  6. a.send(message: "吃饭了吗?")
  7. b.send(message: "没有,你要请吃饭吗?")
  8. a.send(message: "你想多了")

运行结果:

  1. 同事B得到消息:吃饭了吗?
  2. 同事A得到消息:没有,你要请吃饭吗?
  3. 同事B得到消息:你想多了

优点

  • 简化了对象之间的交互。
  • 将各同事解耦。
  • 减少子类生成。
  • 可以简化各同事类的设计和实现。

    缺点

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

    适用环境

    在以下情况下可以使用中介者模式:

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

  • 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
  • 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象。
  • 交互的公共行为,如果需要改变行为则可以增加新的中介者类。

    模式应用

    MVC架构中控制器
    Controller 作为一种中介者,它负责控制视图对象View和模型对象Model之间的交互。如在Struts中,Action就可以作为JSP页面与业务对象之间的中介者。

    模式扩展

    中介者模式与迪米特法则

  • 在中介者模式中,通过创造出一个中介者对象,将系统中有关的对象所引用的其他对象数目减少到最少,使得一个对象与其同事之间的相互作用被这个对象与中介者对象之间的相互作用所取代。因此,中介者模式就是迪米特法则的一个典型应用。

中介者模式与GUI开发

  • 中介者模式可以方便地应用于图形界面(GUI)开发中,在比较复杂的界面中可能存在多个界面组件之间的交互关系。
  • 对于这些复杂的交互关系,有时候我们可以引入一个中介者类,将这些交互的组件作为具体的同事类,将它们之间的引用和控制关系交由中介者负责,在一定程度上简化系统的交互,这也是中介者模式的常见应用之一。

    总结

  • 中介者模式用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。

  • 中介者模式包含四个角色:抽象中介者用于定义一个接口,该接口用于与各同事对象之间的通信;具体中介者是抽象中介者的子类,通过协调各个同事对象来实现协作行为,了解并维护它的各个同事对象的引用;抽象同事类定义各同事的公有方法;具体同事类是抽象同事类的子类,每一个同事对象都引用一个中介者对象;每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信;在具体同事类中实现了在抽象同事类中定义的方法。
  • 通过引入中介者对象,可以将系统的网状结构变成以中介者为中心的星形结构,中介者承担了中转作用和协调作用。中介者类是中介者模式的核心,它对整个系统进行控制和协调,简化了对象之间的交互,还可以对对象间的交互进行进一步的控制。
  • 中介者模式的主要优点在于简化了对象之间的交互,将各同事解耦,还可以减少子类生成,对于复杂的对象之间的交互,通过引入中介者,可以简化各同事类的设计和实现;中介者模式主要缺点在于具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
  • 中介者模式适用情况包括:系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解;一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象;想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。