C++ 中观察者模式与中介者模式的区别

2025年03月22日 | 阅读 6 分钟

本文将概述 C++ 中观察者模式(observer)和中介者模式(mediator)之间的区别。在讨论它们的区别之前,我们必须先了解 C++ 中的观察者模式和中介者模式,包括它们的组成部分和优点。

什么是观察者模式?

观察者模式是一种行为设计模式,表示对象之间的一对多依赖关系。当主体的状态发生变化时,其所有观察者都会自动收到通知并更新。此设计模式用于开发分布式事件处理系统以及许多软件架构中的功能,例如模型-视图-控制器(MVC)

观察者模式的组成部分

  • Subject(主体): 这是状态需要被度量的对象。它维护一个观察者集合,可以添加、删除和通知观察者来更新其外观。
  • Observer(观察者): 此接口定义了主体调用的一个活动,用于通知观察者其内部状态的变化。
  • ConcreteSubject(具体主体): 这是主体的子类,定义了订阅、取消订阅和通知观察者的不同实现。它包含实际状态。
  • ConcreteObserver(具体观察者): 这是观察者接口的子类,实现了 update 方法。每个具体观察者可以根据主体的状态变化决定其自身的行为。

在 C++ 中实现观察者模式的优点

在 C++ 中实现观察者模式的几个优点如下:

  • 事件处理: 它用于GUI 应用程序来捕获来自用户的事件,例如点击按钮,这需要多个组件进行响应。
  • 模型-视图-控制器: MVC 架构,每次模型发生变化时,视图都会自动更新。
  • 自动数据绑定: 每当底层数据发生变化时,UI 组件都会自动更新,从而增强了表单应用程序的用户体验。
  • 实时通知: 它允许用户即时接收所有他们感兴趣内容的更新,例如股票追踪器和社交媒体动态。
  • 日志系统: 多个组件可以注册为观察者,当发生某些事件(例如错误)时,它们会记录日志。
  • 游戏开发: 需要跟踪游戏对象之间的交互,例如监控玩家生命值并在状态发生变化时发出通知。

什么是中介者模式?

中介者是一个对象,它通过要求其他对象直接连接来实现与其他对象的通信,并充当中间人。中介者模式有效地集中了多个对象之间的通信。它减少了通信对象之间的耦合,从而使其更容易更改通信媒介。系统的灵活性得到了提高。中介者模式的解释遵循行为设计模式的思路。

中介者的组成部分

中介者的几个组成部分如下:

  • Mediator(中介者): 中介者定义了一个组织同事之间交互的接口。通常在此接口下声明的方法包括发送、接收消息或协调不同同事之间的操作。
  • Concrete Mediator(具体中介者): 具体中介者是用于实现中介接口的中介者之一,它连接各种本地对象,演示了局部类如何实现“Take”
  • Colleague(同事): 同事定义了一个用于处理中介者的接口或基类。同事对象之间不是直接通信,而是通过中介者进行通信,通过中介者发送和接收消息。
  • Concrete Colleague(具体同事): 具体同事对象实现同事接口,并通过中介者与其他对象进行交互。它们与中介者通信以发送或获取信息,而无需了解其他同事的详细信息。

中介者模式的优点

中介者模式的几个优点如下:

  • 降低耦合度: 耦合降低了同事类之间的直接依赖。同事不再需要了解或相互通信,这使得更改系统变得非常容易。
  • 简化对象交互: 使用一个中心化的中介者来传递所有通信,最大限度地减少了对象相互理解所需的精力,代码易于阅读和维护。
  • 封装控制逻辑: 封装对象间的控制逻辑允许该模式在不修改对象的情况下组合更复杂的对象间交互或协调逻辑。
  • 提高可维护性: 由于交互和协调逻辑集中在一个地方(即中介者),可以在不更改其他类的情况下随时进行修改。

何时使用中介者模式

  • 当多个类以复杂、紧密耦合的方式相互交互时,就需要将它们解耦。
  • 如果我们希望集中控制各个组件如何相互通信,从而使它们更容易修改或扩展。
  • 在任何我们预计会频繁修改一个对象如何与另一个对象交互,而不必更改所有相关类的情况下。

C++ 中观察者模式和中介者模式之间的主要区别

Difference between Observer and Mediator Pattern in C++

C++ 中的观察者模式中介者模式之间有几个主要区别。一些主要区别如下:

特性观察者模式中介者模式
目的在对象状态发生变化或事件发生时,它用于提供一种机制,使一个主体能够与多个观察者进行通信。拥有一个集中的中介者可以实现对象之间的一对多或多对多的交互。
主要关注点通知机制;当主体更改其状态时,观察者会收到通知。集中式通信控制对象之间的交互,因此它们不必直接依赖彼此。
结构主体维护一个观察者列表并与它们通信。中介者定义了一个在同事之间通信的接口,对象仅通过中介者进行交互。
直接通信观察者与主体通信,更新单向流动——向外(主体→观察者)。同事之间不直接通信;相反,所有通信都通过中介者进行。
交互复杂性最适合用于一对多关系,其中许多观察者必须响应主体状态的变化。与其他许多对象交互的对象将交互集中在中介者的位置。
耦合主体和观察者之间的松耦合,并且主体知道所有观察者。它具有更松散的耦合,因为同事不需要相互了解,它们只需要了解中介者。
通知方法主体通知所有已注册观察者其状态更改事件。中介者决定在发生特定触发事件时,同事如何以及何时进行通信。
C++ 实现事件处理机制可以使用函数指针、std::functors 或继承来通知观察者。中介者类作为交互类之间的中间人;每个类都通过中心中介者进行通信。
可重用性有尊严的同事更具可重用性,因为它们不再相互依赖,而只依赖于中介者。可以重新定义中介者本身,而同事保持不变。
可扩展性如果观察者数量非常多,它们可能会效率降低,因为每个观察者都必须单独收到通知。随着同事数量的增加,中介者的复杂性可能会增加,从而变成一个“上帝对象”。
用例事件系统,例如数据更改时进行 UI 更新。
  • 响应式编程。
  • 通知服务。
具有许多交互对象的复杂工作流。
聊天系统、交通控制等需要集中协调的场景。

结论

在 C++ 中,观察者模式中介者模式都存在于对象之间的交互中,并且在不同的场景中各有用途。观察者模式提供了一种一对多的关系,其中一个变化的对象(也称为主体)与所有依赖项和感兴趣的对象(或观察者)进行通信。它最适合于一个组件的状态变化需要通知多个组件的系统,例如在处理事件或模型-视图-控制器时。然而,过多的观察者可能导致高度耦合和性能下降。

另一方面,中介者模式通过中介者协调对象间的交互。对象不直接交互,而是将消息发送给中介者,由中介者协调交互。它最适用于涉及复杂多对多交互的系统,可以减少对象之间的直接依赖并提高可维护性。同时,中介者减少了通信的复杂性。

总而言之,观察者模式通过订阅状态变化来触发其他状态,而中介者模式通过处理对象之间的集中式通信,在更棘手的情况下更为高效。