一、中介者模式简介
中介者模式(Mediator Pattern)是一种行为型设计模式,用于减少对象之间的直接依赖关系,从而简化系统的复杂性。中介者模式通过引入一个中介者对象来管理多个对象之间的交互,确保对象之间不会直接交互,而是通过中介者进行通信。这样可以使对象之间的依赖关系变得更加松散,降低耦合度。简单说,对象之间的交互行为被统一放在中介者对象中,所有对象都通过中介者同其它对象进行交互,中介者对象则起到了调控的作用。
GoF一书对中介者模式的介绍
中介者(Mediator):
- 定义一个接口用于与各个组件进行通信。
- 具体中介者(ConcreteMediator)实现该接口,负责协调各个组件之间的交互。
同事类(Colleague):
- 各个参与交互的对象,通常是需要通过中介者来进行交互的对象。
- 每个同事类对象持有对中介者对象的引用,通过中介者来发送和接收消息。
二、中介者模式的设计方法
演示如何在聊天应用中使用中介者模式。代码设计里聊天服务器(ChatServer)作为中介者,负责处理用户(User)之间的消息传递。用户(fromUser)通过服务器发送消息,服务器将消息转发给接收方用户(toUser)。
mediator.cpp
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
class User;
// 中介者接口
class Mediator {
public:
virtual void send(const std::string& message, const std::string& fromUser, const std::string& toUser) = 0;
virtual void addUser(User* user) = 0;
};
// 同事接口
class User {
public:
User(Mediator* mediator,const std::string& userName) : mediator(mediator), name(userName) {
mediator->addUser(this);
}
std::string getName() const {
return name;
}
virtual void send(const std::string& message, const std::string& toUser) = 0;
virtual void receive(const std::string& message, const std::string& fromUser) = 0;
protected:
Mediator* mediator;
std::string name;
};
// 具体中介者
class ChatServer : public Mediator {
public:
void send(const std::string& message, const std::string& fromUser, const std::string& toUser) override {
if (users.find(toUser) != users.end()) {
users[toUser]->receive(message,fromUser);
}else {
std::cout << "接收消息的用户 " << toUser << " 不存在.\n";
}
}
void addUser(User* user) override {
users[user->getName()] = user;
}
private:
std::unordered_map<std::string, User*> users;
};
// 具体同事
class ConcreteUser : public User {
public:
ConcreteUser(Mediator *mediator, const std::string& UserName) : User(mediator, UserName) {}
void send(const std::string& message, const std::string& toUser) override {
std::cout << name << " sends message: " << message << " to " << toUser << std::endl;
mediator->send(message, name, toUser);
}
void receive(const std::string& message, const std::string& fromUser) override {
std::cout << name << " receive message: " << message << " from " << fromUser << "\n" << std::endl;
}
};
// 客户端
int main() {
ChatServer server;
ConcreteUser tom(&server, "Tom");
ConcreteUser alice(&server, "Alice");
ConcreteUser lucy(&server, "Lucy");
alice.send("Hi, Tom! good morning, are you ok? ", "Tom");
lucy.send("Hello, Alice! How are you? ", "Alice");
tom.send("Hi, Baby! What are you doing? ", "Lucy");
tom.send("good evening! Bob", "Bob");
return 0;
}
运行效果
三、中介者模式应用场景
1. 图形用户界面(GUI)系统
在复杂的用户界面中,可能有多个控件(如按钮、文本框、下拉菜单等),这些控件需要相互交互。例如,当用户选择下拉菜单中的一个选项时,可能需要更新其他控件的状态。中介者模式可以用来管理这些控件之间的交互,使得各个控件不直接依赖于其他控件,而是通过中介者进行协调。
示例:
- 一个表单中,选择某个选项会影响其他控件的可见性或启用状态。中介者可以协调这些控件的状态更新,而不是每个控件直接相互通信。
2. 聊天应用
在聊天应用中,用户之间的消息交流需要通过服务器进行转发。这里,服务器充当了中介者,负责处理用户之间的消息传递,确保消息的发送和接收是有序的。
示例:
- 一个即时通讯软件中,用户之间的消息不会直接发送给对方,而是通过聊天服务器进行中转,服务器处理消息的路由和广播。
3. 协作系统
在多用户协作系统中,多个用户同时操作共享资源(如文档、图表等),需要协调各用户的操作。中介者模式可以用于集中管理这些操作,确保操作的协调性和一致性。
示例:
- 一个在线文档编辑工具中,多个用户同时编辑同一个文档,编辑器通过中介者管理用户的编辑操作,保持文档的一致性和同步性。
4. 业务流程管理
在复杂的业务流程中,多个业务对象(如订单处理、库存管理、发货等)需要协调操作。中介者模式可以用于集中管理这些业务对象之间的交互,确保流程的顺畅和高效。
示例:
- 在电商系统中,订单的处理涉及多个步骤,如库存检查、支付处理、发货等。中介者模式可以帮助管理这些步骤的协调,确保每个步骤按正确的顺序执行。
5. 实时数据流
在实时数据处理系统中,多个数据处理模块需要协调工作。中介者模式可以用于集中管理这些模块的数据流和交互,确保数据处理的正确性和实时性。
示例:
- 在金融市场数据分析系统中,数据的采集、处理、展示可能涉及多个模块。中介者模式可以协调这些模块的数据流动,确保数据处理的实时性和一致性。
6. 系统配置管理
在大型系统中,多个组件可能需要共享配置或状态信息。中介者模式可以用于集中管理这些配置或状态信息,避免组件之间的直接依赖。
示例:
- 在微服务架构中,服务之间可能需要共享配置或状态。中介者模式可以用于集中管理这些配置,使得每个服务不直接依赖其他服务的实现细节。
四、总结
中介者模式集中管理所有对象的交互行为,通过中介者减少对象之间的直接依赖,即不需要各个对象显式的去相互交互,而是由中介者去和各个对象直接交互,一定程度下降低耦合度,并使得系统的设计更加清晰、模块化。