当前位置: 首页 > news >正文

中介者模式与几个C++应用实例

中介者模式 (Mediator Pattern) 深度解析
一、模式定义与核心思想
1. 定义:
中介者模式是一种行为设计模式,它用一个中介对象来封装一系列对象之间的交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

2. 核心思想:

解耦:将原本对象之间复杂的、网状的多对多关系,转变为相对简单的、星形的一对多关系。中介者充当了“交通指挥中心”或“聊天室服务器”的角色。

集中控制:将分散在各个对象中的交互逻辑(通信协议、协调规则)集中到中介者中。这使得这些交互规则更容易理解和修改。

职责分离:各个同事对象(Colleague)只需负责自己的内部状态和行为,它们如何影响其他对象的工作,完全交给了中介者。

二、模式结构(UML 与角色分析)
中介者模式主要包含四个角色:

Mediator (中介者接口):定义了与各同事对象进行通信的接口,通常是一个抽象类或接口,声明了诸如 Notify 的方法。

ConcreteMediator (具体中介者):实现了中介者接口。它知晓所有具体的同事对象,并负责协调各个同事对象之间的交互。它包含了复杂的控制逻辑。

Colleague (同事类接口/基类):定义了同事对象的接口。它通常持有一个指向中介者对象的引用,用于通过中介者与其他同事通信。这个引用通常在构造函数中注入。

ConcreteColleague (具体同事类):实现了同事类接口。每个具体同事对象只知道中介者,而不知道其他同事对象。当需要与其他同事通信时,它会通知中介者。

三、C++ 实现与经典实例

中介者模式的核心在于一个知晓所有同事对象的具体中介者类,它包含了整个系统的交互逻辑。

实例1:聊天室(最经典的例子)

这是一个完美体现中介者模式的场景。多个用户(同事)不需要知道彼此的存在,他们只和聊天室(中介者)打交道。

UML 角色分析:

  • MediatorChatRoomMediator 接口(或抽象类),声明 sendMessage 方法。

  • ConcreteMediatorChatRoom 类,实现 sendMessage,知道所有用户,负责消息的广播。

  • ColleagueUser 基类,持有中介者的引用。

  • ConcreteColleagueChatUser 类,实现发送和接收消息的方法。

C++ 代码实现:

#include <iostream>
#include <string>
#include <vector>
#include <memory>// 1. 前向声明
class User;// 2. Mediator (中介者接口)
class ChatRoomMediator {
public:virtual void sendMessage(const std::string& message, const User* user) = 0;virtual ~ChatRoomMediator() = default;
};// 3. Colleague (同事基类)
class User {
protected:ChatRoomMediator* m_mediator;std::string m_name;public:User(const std::string& name, ChatRoomMediator* mediator): m_name(name), m_mediator(mediator) {}virtual void send(const std::string& message) = 0;virtual void receive(const std::string& message, const std::string& senderName) = 0;const std::string& getName() const { return m_name; }virtual ~User() = default;
};// 4. ConcreteMediator (具体中介者)
class ChatRoom : public ChatRoomMediator {
private:std::vector<User*> m_users; // 中介者知晓所有同事public:void addUser(User* user) {m_users.push_back(user);}void sendMessage(const std::string& message, const User* user) override {// 中介者的核心逻辑:将消息发送给除发送者之外的所有人for (User* u : m_users) {// 不将消息发回给自己if (u != user) { u->receive(message, user->getName());}}// 也可以在这里添加其他逻辑,如记录日志、过滤敏感词等std::cout << "[ChatRoom Log]: " << user->getName() << " sent a message." << std::endl;}
};// 5. ConcreteColleague (具体同事类)
class ChatUser : public User {
public:ChatUser(const std::string& name, ChatRoomMediator* mediator): User(name, mediator) {}void send(const std::string& message) override {std::cout << m_name << " sends: " << message << std::endl;// 关键:同事对象不直接联系其他对象,而是通知中介者m_mediator->sendMessage(message, this);}void receive(const std::string& message, const std::string& senderName) override {std::cout << m_name << " received from " << senderName << ": " << message << std::endl;}
};// 客户端代码
int main() {// 创建中介者ChatRoom chatroom;// 创建同事对象,并将中介者注入给他们ChatUser alice("Alice", &chatroom);ChatUser bob("Bob", &chatroom);ChatUser charlie("Charlie", &chatroom);// 将用户注册到中介者(让中介者知道所有同事)chatroom.addUser(&alice);chatroom.addUser(&bob);chatroom.addUser(&charlie);// 用户通过中介者发送消息,而不是直接相互调用std::cout << "--- Chat Session ---" << std::endl;alice.send("Hi everyone!");bob.send("Hey Alice!");charlie.send("What's up?");return 0;
}

输出:

--- Chat Session ---
Alice sends: Hi everyone!
Bob received from Alice: Hi everyone!
Charlie received from Alice: Hi everyone!
[ChatRoom Log]: Alice sent a message.
Bob sends: Hey Alice!
Alice received from Bob: Hey Alice!
Charlie received from Bob: Hey Alice!
[ChatRoom Log]: Bob sent a message.
Charlie sends: What's up?
Alice received from Charlie: What's up?
Bob received from Charlie: What's up?
[ChatRoom Log]: Charlie sent a message.

模式优势体现:

松耦合:ChatUser 类不知道其他 ChatUser 的存在,它只依赖于 ChatRoomMediator 接口。

易于扩展:要添加新用户,只需创建新的 ChatUser 实例并注册到聊天室即可,无需修改任何现有类。

集中控制:所有消息分发的逻辑(如不发给发送者自己、记录日志)都集中在 ChatRoom::sendMessage 方法中,修改起来非常方便。

实例2:飞机与塔台调度系统
这是一个更复杂、更贴近实际应用的例子,展示了中介者如何管理复杂的交互规则。

场景描述:
多架飞机(同事)需要请求起飞、降落、报告位置。它们不能直接沟通,必须通过塔台(中介者)。塔台知晓所有飞机的状态和机场跑道信息,并根据一套复杂的规则(如跑道是否空闲、优先级)来协调指令。

C++ 代码实现(简化版):

#include <iostream>
#include <string>
#include <map>
#include <memory>// Forward Declarations
class Aircraft;// Mediator
class ControlTower {
private:bool m_runwayAvailable;std::map<std::string, Aircraft*> m_aircrafts; // 所有注册的飞机public:ControlTower() : m_runwayAvailable(true) {}void registerAircraft(const std::string& callSign, Aircraft* aircraft) {m_aircrafts[callSign] = aircraft;}// 中介者的核心协调逻辑void requestLanding(const std::string& aircraftCallSign);void notifyLandingComplete(const std::string& aircraftCallSign);
};// Colleague
class Aircraft {
protected:ControlTower* m_tower;std::string m_callSign;public:Aircraft(const std::string& callSign, ControlTower* tower): m_callSign(callSign), m_tower(tower) {}virtual void requestLanding() {std::cout << m_callSign << " requesting to land." << std::endl;m_tower->requestLanding(m_callSign);}virtual void receiveLandingClearance() {std::cout << m_callSign << " has received landing clearance. Beginning descent." << std::endl;}virtual void completeLanding() {std::cout << m_callSign << " has landed successfully." << std::endl;m_tower->notifyLandingComplete(m_callSign);}virtual ~Aircraft() = default;
};// Concrete Colleague
class PassengerAircraft : public Aircraft {
public:PassengerAircraft(const std::string& callSign, ControlTower* tower): Aircraft(callSign, tower) {}
};// 在类外实现中介者的方法,以避免循环依赖
void ControlTower::requestLanding(const std::string& aircraftCallSign) {if (m_runwayAvailable) {std::cout << "Control Tower: Runway is free. " << aircraftCallSign << " cleared to land." << std::endl;m_runwayAvailable = false;if (m_aircrafts.find(aircraftCallSign) != m_aircrafts.end()) {m_aircrafts[aircraftCallSign]->receiveLandingClearance();}} else {std::cout << "Control Tower: Runway busy. " << aircraftCallSign << " please hold." << std::endl;// 在实际系统中,这里会将请求加入队列}
}void ControlTower::notifyLandingComplete(const std::string& aircraftCallSign) {std::cout << "Control Tower: " << aircraftCallSign << " has vacated the runway." << std::endl;m_runwayAvailable = true;// 检查队列,批准下一架飞机的请求std::cout << "Control Tower: Runway is now available for next aircraft." << std::endl;
}// Client Code
int main() {ControlTower jfkTower;PassengerAircraft ua101("UA101", &jfkTower);PassengerAircraft ba202("BA202", &jfkTower);PassengerAircraft lh303("LH303", &jfkTower);jfkTower.registerAircraft("UA101", &ua101);jfkTower.registerAircraft("BA202", &ba202);jfkTower.registerAircraft("LH303", &lh303);std::cout << "--- Landing Sequence ---" << std::endl;// 飞机只与塔台通信ua101.requestLanding();ba202.requestLanding(); // 这架会被要求等待std::cout << "\n...UA101 is landing...\n" << std::endl;ua101.completeLanding(); // UA101降落完成,释放跑道std::cout << "\nBA202 can now try again..." << std::endl;ba202.requestLanding(); // BA202再次请求,此时跑道空闲return 0;
}

输出:

--- Landing Sequence ---
UA101 requesting to land.
Control Tower: Runway is free. UA101 cleared to land.
UA101 has received landing clearance. Beginning descent.
BA202 requesting to land.
Control Tower: Runway busy. BA202 please hold....UA101 is landing...UA101 has landed successfully.
Control Tower: UA101 has vacated the runway.
Control Tower: Runway is now available for next aircraft.BA202 can now try again...
BA202 requesting to land.
Control Tower: Runway is free. BA202 cleared to land.
BA202 has received landing clearance. Beginning descent.

http://www.xdnf.cn/news/1360603.html

相关文章:

  • imx6ull-驱动开发篇39——Linux INPUT 子系统实验
  • 【基础算法】初识搜索:递归型枚举与回溯剪枝
  • 【ElasticSearch】springboot整合es案例
  • Smooze Pro for mac 鼠标手势增强软件
  • 【C语言练习】青蛙跳台阶
  • Vue状态管理工具pinia的使用以及Vue组件通讯
  • 强光干扰下检出率↑93%!陌讯多模态融合算法在充电桩车位占用检测的实战解析
  • 力扣【1277. 统计全为1的正方形子矩阵】——从暴力到最优的思考过程
  • 【网络运维】Shell脚本编程:函数
  • 深度学习之第二课PyTorch与CUDA的安装
  • AOSP构建指南:从零开始的Android源码之旅
  • Docker 容器(一)
  • 【Docker基础】Docker-compose常用命令实践(三):镜像与配置管理
  • 【零代码】OpenCV C# 快速开发框架演示
  • 电路学习(四)二极管
  • 【计算机视觉】CaFormer
  • Java:LinkedList的使用
  • 【Protues仿真】基于AT89C52单片机的温湿度测量
  • 【文献阅读】生态恢复项目对生态系统稳定性的影响
  • 在JavaScript中,比较两个数组是否有相同元素(交集)的常用方法
  • 解决编译osgEarth中winsocket2.h找不到头文件问题
  • Node.js自研ORM框架深度解析与实践
  • C++11新特性全面解析(万字详解)
  • Starlink第三代终端和第二代终端的差异性有哪些?
  • Flink SQL执行SQL错误排查
  • MySQL的安装和卸载指南(入门到入土)
  • ZKmall模块商城的推荐数据体系:从多维度采集到高效存储的实践
  • 从“小麻烦”到“大难题”:Spring Boot 配置文件的坑与解
  • 04-ArkTS编程语言入门
  • 使用UE5开发《红色警戒3》类战略养成游戏的硬件配置指南