中介者模式详解(附带C++实例)
在系统设计中,随着组件数量的增加和交互的复杂化,有效地管理这些组件之间的通信成为一个不容忽视的挑战。中介者模式为我们提供了一种优雅的解决方案,它通过一个中介对象来封装一系列对象之间的交互方式。
中介者模式特别适用于以下几种应用需求:
在思考这些需求的时候,我们可以问自己几个问题来评估是否适合采用中介者模式:
当我们对这些问题有了答案后,就可以更深入地探讨中介者模式的具体应用了。

图 1 中介者模式
它主要包含以下几个关键角色:
例如,在一个在线协作系统中,可能包括文档编辑器、聊天窗口、用户列表等多个组件。这些组件需要频繁地互相交流,比如更新文档状态、发送消息通知等。在没有中介者的设计中,这些组件之间的直接引用和调用会导致系统耦合度增加,使得维护和扩展变得困难。
引入中介者后,所有组件的交互都通过中介者对象进行。当用户在文档编辑器中做出更改时,编辑器只需通知中介者,由中介者来通知其他相关组件更新状态。这种方式解除了组件之间的直接依赖关系,使得每个组件只需要与中介者交互。
这样设计,不仅简化了组件之间的通信逻辑,还降低了系统的耦合度,组件的替换和修改也变得更加方便。即使交互逻辑发生变化,也只需调整中介者,而无须修改所有组件的代码,从而提高了系统的可维护性和可扩展性。
当一个具体同事类(比如 ConcreteColleagueA)发送消息时,它会调用中介者的 communicate 方法,这个方法会让其他的同事类接收到消息,从而完成各个组件之间的交互。
这样可以避免以下问题:
总之,中介者模式通过将交互逻辑集中到一个中介者中来管理,降低了系统内各部分之间的耦合,简化了组件的设计和维护,提高了系统的灵活性和可扩展性。这种模式特别适合用于复杂的交互系统,例如大型 GUI 应用程序或业务流程管理系统。
中介者模式特别适用于以下几种应用需求:
- 大量组件互动:当系统中的组件数量很多,且彼此间需要频繁交互时,直接的通信会导致难以管理的依赖关系和高耦合度。中介者模式允许这些组件不直接通信,而是通过一个中心点来协调交互,从而降低系统的复杂性;
- 改变交互逻辑:在系统需求频繁变更的情况下,如果交互逻辑直接嵌入组件中,每次变更都可能需要修改多个组件。中介者模式使得交互逻辑集中于一个地方,更改时只需调整中介者即可;
- 复用组件:当需要在不同的上下文中复用组件时,如果这些组件高度依赖于特定的交互逻辑,复用就会变得非常困难。通过使用中介者模式,组件可以更加独立和通用,易于在不同的场景下复用。
在思考这些需求的时候,我们可以问自己几个问题来评估是否适合采用中介者模式:
- 系统中是否存在多个组件需要频繁交互?
- 是否希望能够轻松更改组件之间的交互逻辑?
- 是否需要在不同的场景中复用某些组件?
当我们对这些问题有了答案后,就可以更深入地探讨中介者模式的具体应用了。
中介者模式中的角色
中介者模式如下图所示:
图 1 中介者模式
它主要包含以下几个关键角色:
- 中介者接口:定义了中介者的基本行为,即用于与各个组件通信的方法。所有具体的中介者类都需要实现这个接口,从而在系统中充当协调者的角色;
- 具体中介者:实现中介者接口,并负责协调各个组件之间的交互。具体中介者知道所有的同事类,并通过提供集中控制的机制,管理组件间的通信和依赖,解除组件之间的直接依赖关系。例如,当某个组件需要与其他组件通信时,它不再直接与这些组件通信,而是通过中介者进行。这使得组件可以独立开发和修改,而无须关注其他组件的具体实现;
- 同事类接口:同事类是系统中各个对象的基类,它们通过继承同事类来实现自己的特定功能。每个同事类都包含一个指向中介者对象的引用,从而可以通过中介者与其他同事类进行通信,而无须直接引用这些同事类。
例如,在一个在线协作系统中,可能包括文档编辑器、聊天窗口、用户列表等多个组件。这些组件需要频繁地互相交流,比如更新文档状态、发送消息通知等。在没有中介者的设计中,这些组件之间的直接引用和调用会导致系统耦合度增加,使得维护和扩展变得困难。
引入中介者后,所有组件的交互都通过中介者对象进行。当用户在文档编辑器中做出更改时,编辑器只需通知中介者,由中介者来通知其他相关组件更新状态。这种方式解除了组件之间的直接依赖关系,使得每个组件只需要与中介者交互。
这样设计,不仅简化了组件之间的通信逻辑,还降低了系统的耦合度,组件的替换和修改也变得更加方便。即使交互逻辑发生变化,也只需调整中介者,而无须修改所有组件的代码,从而提高了系统的可维护性和可扩展性。
中介者模式示例展示
#include <iostream> #include <vector> // 中介者接口定义与各组件通信的方法 class Mediator { public: virtual void communicate(const std::string& message, class Colleague* colleague) = 0; }; // 同事类接口,组件知晓中介者但不知晓其他同事类 class Colleague { protected: Mediator* mediator; public: Colleague(Mediator* m) : mediator(m) {} virtual void receiveMessage(const std::string& message) = 0; virtual void sendMessage(const std::string& message) = 0; }; // 具体中介者,实现中介者接口,协调各组件间的交互 class ConcreteMediator : public Mediator { private: std::vector<Colleague*> colleagues; public: void addColleague(Colleague* colleague) { colleagues.push_back(colleague); } void communicate(const std::string& message, Colleague* originator) override { for (auto* colleague : colleagues) { if (colleague != originator) { // 发送信息给除了发起者之外的所有同事 colleague->receiveMessage(message); } } } }; // 具体同事类A class ConcreteColleagueA : public Colleague { public: ConcreteColleagueA(Mediator* m) : Colleague(m) {} void receiveMessage(const std::string& message) override { std::cout << "同事A收到消息:" << message << std::endl; } void sendMessage(const std::string& message) override { std::cout << "同事A发送消息:" << message << std::endl; mediator->communicate(message, this); } }; // 具体同事类B class ConcreteColleagueB : public Colleague { public: ConcreteColleagueB(Mediator* m) : Colleague(m) {} void receiveMessage(const std::string& message) override { std::cout << "同事B收到消息:" << message << std::endl; } void sendMessage(const std::string& message) override { std::cout << "同事B发送消息:" << message << std::endl; mediator->communicate(message, this); } }; int main() { ConcreteMediator mediator; ConcreteColleagueA colleagueA(&mediator); ConcreteColleagueB colleagueB(&mediator); mediator.addColleague(&colleagueA); mediator.addColleague(&colleagueB); colleagueA.sendMessage("你好,同事B"); colleagueB.sendMessage("你好,同事A,今天感觉怎么样?"); return 0; }运行结果为:
同事A发送消息:你好,同事B
同事B收到消息:你好,同事B
同事B发送消息:你好,同事A,今天感觉怎么样?
同事A收到消息:你好,同事A,今天感觉怎么样?
- Mediator 是一个中介者接口,定义了通信的抽象方法;
- ConcreteMediator 是具体的中介者,管理了同事对象的交互;
- Colleague 是同事类的接口,提供了接收和发送消息的方法;
- ConcreteColleagueA 和 ConcreteColleagueB 是实现了同事接口的具体类。
当一个具体同事类(比如 ConcreteColleagueA)发送消息时,它会调用中介者的 communicate 方法,这个方法会让其他的同事类接收到消息,从而完成各个组件之间的交互。
中介者模式的作用
中介者模式在软件设计中的主要作用如下:- 降低耦合度:通过引入一个中介者对象,各个同事类(即组件)不再直接通信。它们只与中介者交互,这意味着任何同事类之间的交互逻辑都被封装在中介者中。这样,每个组件都只依赖于一个中介者而不是多个组件,从而降低了系统的耦合度;
- 集中控制交互逻辑:所有的交互逻辑都集中在中介者中进行管理,使得这些逻辑更容易修改和维护。例如,如果交互规则发生变化,只需修改中介者而无须修改各个同事类;
- 简化组件设计:同事类可以更专注于自己的功能实现,它们不需要处理与其他组件的直接通信。这使得每个组件的设计和实现都更简单,也更容易理解和维护;
- 提高可扩展性:在中介者模式下添加新的同事类变得更简单,因为新的组件只需与中介者进行交互,而不需要知道系统的所有细节。这使得扩展系统功能或添加新的功能变得更容易。
这样可以避免以下问题:
- 避免直接依赖和形成复杂的网络关系:在没有中介者的情况下,每个组件可能需要直接与多个其他组件通信,形成复杂的网络关系。这种设计不仅使系统难以理解和扩展,还可能导致各种运行时错误;
- 减少修改时的影响范围:当系统中的通信逻辑需要修改时,如果没有中介者模式,可能需要修改多个组件的代码。这样做增加了出错的风险,并可能引入新的缺陷。而有了中介者,通常只需修改中介者的代码即可,其他同事类保持不变。
总之,中介者模式通过将交互逻辑集中到一个中介者中来管理,降低了系统内各部分之间的耦合,简化了组件的设计和维护,提高了系统的灵活性和可扩展性。这种模式特别适合用于复杂的交互系统,例如大型 GUI 应用程序或业务流程管理系统。