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

C++设计模式:中介者模式(聊天室系统)

什么是中介者模式?

中介者模式是一种行为型设计模式,它定义了一个中介者对象,用来封装一组对象之间的交互逻辑,从而使这些对象之间的关系更加松散,减少对象之间的直接依赖。

通俗解释:
  • 中介者模式可以类比于一个会议主持人
    在一个会议中,每个与会者不能直接与其他人沟通,而是通过主持人来协调发言和讨论,这样与会者之间的耦合就被移除了,会议流程变得有条理。

在程序中,中介者对象管理并协调多个对象之间的通信,使得对象之间的依赖从直接耦合变为间接耦合。


中介者模式的适用场景

什么时候使用中介者模式?
  • 系统中有多个对象需要互相通信,每个对象之间耦合过于复杂。
  • 对象之间的交互逻辑不断变化,需要一个集中管理的机制。
  • 希望通过一个中心点控制所有对象之间的交互。
例子:
  1. 聊天室系统:用户之间通过聊天室(中介者)发送消息,而不是直接通信。
  2. 机场调度系统:各个飞机之间通过调度塔(中介者)通信,避免直接相互协调。
  3. MVC架构:Controller可以看作是中介者,协调Model和View之间的通信。

中介者模式的结构

UML 类图
          +-------------------+
          |    Mediator       |  // 中介者接口
          +-------------------+
                     ^
                     |
          +-------------------+
          | ConcreteMediator  |  // 具体中介者
          +-------------------+
                     ^
                     |
          +-------------------+
          |     Colleague     |  // 同事类
          +-------------------+
                     ^
                     |
     +-----------------------+
     | ConcreteColleagueA    |  // 具体同事类A
     +-----------------------+
     | ConcreteColleagueB    |  // 具体同事类B
     +-----------------------+
组成部分:
  1. Mediator(中介者接口)
    定义了同事类之间通信的接口。

  2. ConcreteMediator(具体中介者)
    实现中介者接口,协调各个同事类之间的交互逻辑。

  3. Colleague(同事类)
    定义同事类的通用行为,通过中介者来与其他同事通信。

  4. ConcreteColleague(具体同事类)
    实现同事类的具体行为,它们只与中介者通信,而不是直接与其他同事通信。


中介者模式的优缺点

优点:
  1. 降低耦合性:同事类之间不再直接通信,而是通过中介者进行交互,解耦对象之间的依赖。
  2. 集中控制交互:交互逻辑集中在中介者中,便于维护和修改。
  3. 简化对象通信:通过中介者,同事类只需要与中介者打交道,减少了复杂的网状通信。
缺点:
  1. 中介者复杂性增加:随着同事类数量的增加,中介者的逻辑可能会变得非常复杂。
  2. 可能导致性能问题:所有通信都通过中介者处理,可能成为性能瓶颈。

案例:聊天室系统

需求描述

我们需要设计一个简单的聊天室系统:

  1. 多个用户可以加入聊天室。
  2. 用户发送消息时,消息会通过聊天室转发给其他用户。
  3. 每个用户只与聊天室通信,而不是直接与其他用户通信。

代码实现

以下是完整的代码实现,输出信息为中文,并配有详细注释。

#include <iostream>
#include <string>
#include <vector>
#include <memory>

// 中介者接口
class Mediator {
public:
    virtual void sendMessage(const std::string& message, const std::string& sender) = 0; // 发送消息接口
    virtual void addUser(std::shared_ptr<class Colleague> user) = 0; // 添加用户接口
    virtual ~Mediator() = default;
};

// 同事类(用户基类)
class Colleague {
public:
    std::string name; // 用户名
    std::shared_ptr<Mediator> mediator; // 中介者引用

public:
    Colleague(const std::string& name, std::shared_ptr<Mediator> mediator) 
        : name(name), mediator(mediator) {}

    virtual void send(const std::string& message) = 0; // 发送消息
    virtual void receive(const std::string& message, const std::string& sender) = 0; // 接收消息
    virtual ~Colleague() = default;
};

// 具体同事类(用户类)
class User : public Colleague {
public:
    User(const std::string& name, std::shared_ptr<Mediator> mediator) 
        : Colleague(name, mediator) {}

    // 发送消息
    void send(const std::string& message) override {
        std::cout << name << " 发送消息: " << message << std::endl;
        mediator->sendMessage(message, name); // 通过中介者发送消息
    }

    // 接收消息
    void receive(const std::string& message, const std::string& sender) override {
        std::cout << name << " 收到来自 " << sender << " 的消息: " << message << std::endl;
    }
};

// 具体中介者类(聊天室)
class ChatRoom : public Mediator {
private:
    std::vector<std::shared_ptr<Colleague>> users; // 聊天室中的用户列表

public:
    // 添加用户到聊天室
    void addUser(std::shared_ptr<Colleague> user) override {
        users.push_back(user);
    }

    // 发送消息给其他用户
    void sendMessage(const std::string& message, const std::string& sender) override {
        for (const auto& user : users) {
            // 不将消息发给发送者自己
            if (user->name != sender) {
                user->receive(message, sender);
            }
        }
    }
};

// 客户端代码
int main() {
    // 创建聊天室(中介者)
    auto chatRoom = std::make_shared<ChatRoom>();

    // 创建用户并加入聊天室
    auto user1 = std::make_shared<User>("张三", chatRoom);
    auto user2 = std::make_shared<User>("李四", chatRoom);
    auto user3 = std::make_shared<User>("王五", chatRoom);

    chatRoom->addUser(user1);
    chatRoom->addUser(user2);
    chatRoom->addUser(user3);

    // 用户发送消息
    user1->send("大家好,我是张三!");
    user2->send("你好张三,我是李四!");
    user3->send("你好张三和李四,我是王五!");

    return 0;
}

运行结果

运行以上代码后,输出如下:

张三 发送消息: 大家好,我是张三!
李四 收到来自 张三 的消息: 大家好,我是张三!
王五 收到来自 张三 的消息: 大家好,我是张三!
李四 发送消息: 你好张三,我是李四!
张三 收到来自 李四 的消息: 你好张三,我是李四!
王五 收到来自 李四 的消息: 你好张三,我是李四!
王五 发送消息: 你好张三和李四,我是王五!
张三 收到来自 王五 的消息: 你好张三和李四,我是王五!
李四 收到来自 王五 的消息: 你好张三和李四,我是王五!

代码讲解

1. 中介者接口
class Mediator {
public:
    virtual void sendMessage(const std::string& message, const std::string& sender) = 0;
    virtual void addUser(std::shared_ptr<class Colleague> user) = 0;
    virtual ~Mediator() = default;
};
  • 定义了sendMessageaddUser方法,用于处理消息和用户管理。
  • Mediator是中介者的抽象接口,具体中介者需要实现它。

2. 具体中介者类(聊天室)
class ChatRoom : public Mediator {
private:
    std::vector<std::shared_ptr<Colleague>> users;

public:
    void addUser(std::shared_ptr<Colleague> user) override {
        users.push_back(user);
    }

    void sendMessage(const std::string& message, const std::string& sender) override {
        for (const auto& user : users) {
            if (user->name != sender) {
                user->receive(message, sender);
            }
        }
    }
};
  • ChatRoom作为具体的中介者,负责管理用户,并协调消息的发送。
  • 消息不会发送给消息的发送者自己。

3. 同事类(用户基类)
class Colleague {
public:
    std::string name;
    std::shared_ptr<Mediator> mediator;

public:
    Colleague(const std::string& name, std::shared_ptr<Mediator> mediator) 
        : name(name), mediator(mediator) {}

    virtual void send(const std::string& message) = 0;
    virtual void receive(const std::string& message, const std::string& sender) = 0;
    virtual ~Colleague() = default;
};
  • 定义了sendreceive方法,供具体同事类实现。
  • 每个同事类持有一个中介者的引用。

4. 具体同事类(用户)
class User : public Colleague {
public:
    User(const std::string& name, std::shared_ptr<Mediator> mediator) 
        : Colleague(name, mediator) {}

    void send(const std::string& message) override {
        std::cout << name << " 发送消息: " << message << std::endl;
        mediator->sendMessage(message, name);
    }

    void receive(const std::string& message, const std::string& sender) override {
        std::cout << name << " 收到来自 " << sender << " 的消息: " << message << std::endl;
    }
};
  • 用户类通过中介者发送和接收消息,避免了与其他用户的直接交互。

总结

中介者模式的核心优势:
  1. 降低耦合:各个同事类通过中介者交互,无需直接依赖其他同事类。
  2. 集中管理交互逻辑:中介者负责协调同事类之间的通信,使得系统的交互逻辑清晰。
适用场景:
  • 聊天室系统:用户通过聊天室发送消息。
  • 航班调度系统:飞机通过调度塔通信。
  • UI组件交互:各组件通过中介者(Controller)协调。

通过本案例,我们清晰地展示了中介者模式如何简化对象之间的交互逻辑,提高代码的灵活性和可维护性!


http://www.kler.cn/a/450254.html

相关文章:

  • Jenkins 任意文件读取(CVE-2024-23897)修复及复现
  • SpringBoot简单使用Stomp
  • 【网络安全产品大调研系列】1. 漏洞扫描
  • 【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
  • 什么是MVCC?
  • linux firewalld 命令详解
  • 线性控制算法与非线性控制算法阐述与区分
  • 谷歌浏览器“你使用的是不受支持的命令行标志:--no-sandbox。这会带来稳定性和安全风险。”解决方法
  • NestJS中使用DynamicModule构建插件系统
  • EasyGBS国标GB28181公网平台P2P远程访问故障诊断:云端服务端排查指南
  • 微服务——技术选型与框架
  • PingCAP TiDB数据库专员PCTA认证笔记
  • 【杂谈】-为什么Python是AI的首选语言
  • C# winform 字符串通过枚举类型转成int类型的数据
  • 【全栈实战】基于 Vue3 + Wot Design Uni 动手封装组件
  • 低代码可视化-uniapp进销存销售表单-代码生成器
  • LeetCode 2605 从两个数字数组里生成最小数字
  • Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
  • Echarts的高级使用,动画,交互api
  • Vue3:uv-upload图片上传
  • LeetCode:101. 对称二叉树
  • Vue3 组件 view-shadcn-ui 2024.5.3 发布
  • 如何利用Java爬虫按关键字搜索苏宁易购商品
  • 精准提升:从94.5%到99.4%——目标检测调优全纪录
  • 搭建Docker Harbor仓库
  • Qt5 cmake引用private头文件