概述
调解器设计模式是一种行为设计模式。它是使用最广泛和最重要的设计模式类型之一。中介器设计模式通过添加中介器(即用于抑制它们之间直接交互的层)来分离对象,从而限制对象之间的直接通信,从而强制通过它进行通信。
我们什么时候需要调解器设计模式?
如果对象直接相互交互,则系统组件将彼此紧密连接,从而增加可维护性成本并易于扩展。中介模式侧重于充当项目之间的桥梁,以促进沟通并帮助实现组件之间的失耦合。中介模式用于降低许多对象或类之间通信的复杂性。中介器设计模式指定一个对象,该对象封装一组项如何相互通信。
我们习惯于看到由大量课程组成的程序。但是,当将其他类引入程序时,这些类之间的通信问题可能会变得更加困难。因此,维护已成为必须以某种方式解决的主要问题。
与许多其他设计模式一样,中介模式似乎解决了这个问题。它促进了中介对象所包含的项之间的通信。对象之间不直接通信,而是通过中介进行通信。
可以使用中介器设计模式的方案
调解器模式可用于以下方案:
-
当你发现自己创建了大量的组件子类,只是为了在不同的上下文中重用一些基本行为时 - 因为组件之间的所有关系都包含在中介中,所以通过添加额外的中介类来定义这些组件协作的替代方法很简单,而不需要改变组件本身。
-
当由于某些类与大量其他类密切相关而难以更改它们时,中介器设计模式允许您将类之间的所有关系隔离到一个新类中,将对单个组件的任何更改与其余组件分开。
-
当您无法在另一个应用程序中重用某个组件时,因为它过于依赖其他组件 - 当您使用调解器时,各个组件会忽略其他组件。他们仍然可以相互交流,尽管是通过调解人项目。如果要重用另一个项目中的组件,则必须为其提供新的中介类。
调解器设计模式示例
- 聊天应用程序是中介器设计的一个常见示例。我们可以在一个聊天应用程序中有多个参与者,将每个参与者相互连接会对隐私和安全造成损害,并且还会增加连接数量。最安全的选择是拥有一个所有参与者都可以连接的中心位置;这个中心位置就是 Mediator 类。
- 机场的交通控制室是调解器设计模式的一个奇妙的真实例证。如果所有航班都要相互交谈以弄清楚下一个航班将到达,那将是一场巨大的灾难。相反,航班只是将其状态传输到塔台。这些塔又传递信号,以确定飞机是否可以起飞或降落。重要的是要意识到这些塔并不能控制整个飞行。它们仅在终端区域实施限制。
在本文中,我们将研究一个通信系统,其中用英语交谈的人 A 正在与一群说不同语言且无法准确理解英语的人进行交流。同样,A只能用英语交流,无法理解他人所说的语言。
在这里,实时字幕系统充当调解员,协助沟通过程。如果他们试图直接沟通,他们往往会发出错误的信号,并更加混淆对方。字幕系统将充当通话人员之间的路由器,并有自己的逻辑来提供通信方式。
调解器设计模式如何工作?
调解器是控制一组项目如何相互通信的实体。协作对象之间的松散耦合是通过让它们与调解器通信而不是彼此通信来完成的。实时字幕系统非常有效地演示了这种模式。通话的每个与会者都会将字幕设置为他们的语言。当 A 发言时,字幕系统(调解员)将在相应与会者的屏幕上以必要的语言显示消息。
绝不会,参与者将直接相互交流。作为调解人的字幕系统不会控制与会者的行为。它的存在只是为了通过有效翻译他们的信息来加强沟通。
结构
1. 组件是提供业务逻辑的不同类。每个组件都有一个对调解器的引用,该调解器由调解器接口的类型指定。由于组件不知道中介的实际类,因此可以通过将其附加到其他中介来在其他项目中重用它。
2. 调解器接口指定了与组件的通信方法,这些组件通常只包含一个通知方法。组件可以将任何上下文(包括它们自己的对象)作为参数传递给此函数,但只能以接收组件和发送方的类之间不存在耦合的方式传递。
3. 具体中介包含不同组件的相互作用。混凝土调解员经常跟踪他们管理的所有组件,在某些情况下,管理他们的整个生命周期。
4. Concrete Colleague 使用其中介与其他同事交谈,并实现同事接口。
组件不得意识到其他组件的存在。如果组件内部或组件发生任何重大事件,则组件必须仅向调解器发出警报。当调解员收到通知时,它可以简单地识别发送者,这可能足以确定应援引哪个组件作为回应。从组件的角度来看,一切似乎都是一个完整的黑匣子。发送方不知道谁将处理请求,接收方也不知道谁首先发出了请求。
实现
在此示例中,考虑到一般情况,主持会议的人员必须学习每种语言,并找到一种同时相互交流的方法。这将是一个非常复杂的过程。但是,调解器模式有助于消除呼叫中不同人员之间的相互依赖关系。
尽管通话中的不同参与者似乎在直接交流,但事实并非如此。相反,参与者只需要检查字幕系统即可理解消息,然后在不了解其他与会者使用的单词及其含义的情况下发言。
实施解决方案时要遵循的步骤
1. 确定一组紧密相连的类,这些类可能会从更多的独立性中受益。
2. 定义调解器接口以及调解器与其他组件之间的适当通信协议。当您希望在多种情况下重用组件类时,此接口至关重要。您可以将组件与其他调解器实现链接,只要该组件使用常规接口与其调解器进行通信即可。
3.将具体的调解员类付诸行动。此类将受益于跟踪它维护的所有组件。您可以更进一步,让调解器对组件对象的创建和销毁负责。之后,调解员可能会呈现出工厂或门面的外观。
4. 中介对象应由组件引用。连接通常在组件的连接器中进行,其中中介对象作为参数提供。
5. 修改组件的代码,以便它们调用中介的通知方法,而不是其他组件上的方法。将调用其他组件的代码提取到中介类中。当调解器从该组件收到警报时,请运行此代码。
伪代码
// The mediator interface declares a method used by components to notify the mediator about various events.
interface Mediator is
method notify(sender: Component, language: string)
// The concrete mediator class.
class Chat implements Mediator is
private field message: string
private field speaker, listener: User
private field isLanguageAccepted: Checkbox
constructor Chat() is
// When something happens with a component, it notifies the mediator. Upon receiving a notification, the mediator may do something on its own or pass the request to another component.
method notify(sender, language) is
// if the language is filled into the system and can be translated, then it will inform the mediator regarding this and accordingly proceed with translation.
// Components communicate with a mediator using the mediator interface.
class Component is
field message: Mediator
constructor Component(message) is
this.message = message
method translate() is
// check the language to be translated and change the message based on the translated value
// Concrete components don't talk to each other. They have only one communication channel, which is sending notifications to the mediator. So our concrete components A and B (different people) share their message with each other after it getting translated using the mediator.
class User extends Component is
// ...
class Language extends Component is
// ...
class Checkbox extends Component is
// ...
调解器设计模式的优缺点
优点:
- 单一责任原则:通过将众多组件整合到一个位置,减少它们之间的通信路径,使它们更易于理解和管理。
- 开/闭原理:您可以在不更改实际组件的情况下添加其他介质。
- 单个组件的重用:它限制了子类化。调解器指导可能分散在多个对象中的操作。子类化 Mediator 是改变这种行为的唯一方法;同事类可以按原样重用。
- 简单性:您可以在不更改类或接口的情况下将结构中的一个项目换成另一个项目。
缺点:
- 控制的集中化:中介模式将交互复杂性与中介复杂换。调解员可能会变得比任何同事都更复杂,因为它包含协议。这可能导致调解器成为难以维护的单体。
- 亲密的调解人行为:随着时间的推移,调解人可能会成长为上帝对象。调解员经常必须非常熟悉所有不同的类别。
- 复杂性:中介对象负责参与者对象之间的所有交互。当参与者数量和不同的参与者类很大时,就会出现中介复杂性的潜在问题。如果您曾经为图形用户界面 (GUI) 应用程序编写过自定义对话,您会记得对话类在一段时间后变得非常复杂。
- 难以维护:调解器的复杂性及其集中控制的性质使其难以维护。
调解器设计模式与其他设计模式的区别
调解器与外观模式
中介设计模式类似于外观设计模式。您无需在调解器中处理单个对象的接口,而是在多个对象之间创建多路复用接口,以实现无缝转换。中介器与 Facade 一样,将功能与现有类隔离开来。在调解器中,调解器增加了功能,因此被同事对象知道。另一方面,Facade 定义了子系统的简化接口;它不引入其他功能,并且对子系统类是未知的。
调解器模式与适配器模式
中介模式只是“中介”同事类之间的请求。它并不意味着改变它接收和传输的消息;如果是这样,则它是适配器设计模式。
调解器模式与观察者模式
观察者和中介设计解决同一问题的模式。它们之间的根本区别在于它们所解决的问题。区别在于,Observer 对象通过插入“观察者”和“主体”对象来传播通信,而 Mediator 对象包含其他对象之间的通信。中介类最有可能在中介设计模式中继承。调解器和观察者的设计模式是相反的。人们发现,创建可重用的观察者和主体比创建可重用的中介更容易。
总结
- 中介设计模式是行为设计模式中最重要的形式之一。
- 中介器设计模式通过分离项目并添加中介器(即“阻碍它们之间直接交互的层”)来限制项目之间的直接连接,从而强制通过它进行通信。
- 它解决了多个类之间的通信问题。
- 中介器设计模式用于存在多个类的情况,并且由于它们依赖于其他组件而难以更改其行为或重用它们。
- 调解器设计模式的常见示例是社交媒体聊天组调解器、机场交通控制室和翻译器。
- 基本的中介模式设计结构包含组件、中介接口、具体中介和具体同事。
- 中介器设计模式减少了组件之间的通信路径,使它们更易于理解,并增强了代码的可重用性。
- 由于中介的集中控制性质,调解器的维护很复杂。
常见问题
问:说出 Mediator Design Pattern 的 2 种实际用途。
答:
1.在用户界面方面,中介模式是最常用的设计模式。它是几乎所有 GUI 框架的基础。表示窗体的类(Dialog、Form、Button、Checkbox 等)表示中介,而每个控件表示一个同事。窗体类提供与控件交互的方法;生成新屏幕时,会生成一个继承的类,并在该类中编写相关代码。这种形式的类充当控制通信的管道。
2. Java 消息服务 (JMS) API 是一个 Java 面向消息的中间件 (MOM) API,它允许在两个或多个客户端之间发送消息。JMS API 支持两种模型。发布-订阅模型就是其中之一。它是一种中介模式实现。可以根据某个主题发布消息。发布者必须设置一个订阅,各种订阅者都可以订阅。如果订阅者为零或更多,则订阅者可以订阅接收有关某个消息主题的消息。发布者和订阅者彼此一无所知,订阅者甚至可能处于非活动状态。在这种情况下,订阅者将在它变为活动状态时收到消息。
问:单中介类需要抽象中介吗?
答:只要同事只使用一个中介,就不需要构建抽象中介类或接口。只有当同事需要与不同的调解员打交道时,抽象调解员的概念才变得必要。
问:调解员和同事之间如何建立沟通?
答:有几种方法可以在同事和调解员之间建立沟通: * 可以采用基本委托,调解人对象可以提供专门的方法。 * 在更复杂的实现中,可以将异步消息添加到消息队列中,从中获取中介对象。 * 观察者模式可以投入使用。在这种情况下,调解人也可以充当观察者,同事可以充当可观察对象的实现者。每当对对象进行状态更改时,调解者(观察者)都会收到通知,并进一步通知所有同事。
问:责任链设计模式与调解人设计模式有何不同?
答:责任链、命令、调解者和观察者的设计模式解决了如何分离发送方和接收方的问题,尽管需要权衡取舍。发送方请求使用责任链通过可能的接收者链进行路由。与子类的发送方-接收方关系通常由命令指定。发件人和收件人由调解员间接提及。Observer 提供了一个相对解耦的接口,可以在运行时配置许多接收器。