C++ 设计模式之 中介者模式

【声明】本题目来源于卡码网(题目页面 (kamacoder.com))

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】


【设计模式大纲】


【简介】

        -- 什么是中介者模式 (第16种模式)

        中介者模式(Mediator Pattern)也被称为调停者模式,是⼀种⾏为型设计模式,它通过⼀个中介对象来封装⼀组对象之间的交互,从⽽使这些对象不需要直接相互引⽤。这样可以降低对象之间的耦合度,使系统更容易维护和扩展。
        当⼀个系统中的对象有很多且多个对象之间有复杂的相互依赖关系时,其结构图可能是下⾯这样的。

        这种依赖关系很难理清,这时我们可以引⼊⼀个中介者对象来进⾏协调和交互。中介者模式可以使得系统的⽹状结构变成以中介者为中⼼的星形结构,每个具体对象不再通过直接的联系与另⼀个对象发⽣相互作⽤,⽽是通过“中介者”对象与另⼀个对象发⽣相互作⽤。


 

【基本结构】

        中介者模式包含以下⼏个基本角色:

  • 抽象中介者(Mediator): 定义中介者的接⼝,⽤于各个具体同事对象之间的通信。
  • 具体中介者(Concrete Mediator): 实现抽象中介者接⼝,负责协调各个具体同事对象的交互关系,它需要知道所有具体同事类,并从具体同事接收消息,向具体同事对象发出命令。
  • 抽象同事类(Colleague): 定义同事类的接⼝,维护⼀个对中介者对象的引⽤,⽤于通信。
  • 具体同事类(Concrete Colleague): 实现抽象同事类接⼝,每个具体同事类只知道⾃⼰的⾏为,⽽不了解其他同事类的情况,因为它们都需要与中介者通信,通过中介者协调与其他同事对象的交互。


 

【简易实现 - Java】

        以Java代码先作以说明:

1. 抽象中介者

// 抽象中介者
public abstract class Mediator {
    void register(Colleague colleague);
    // 定义⼀个抽象的发送消息⽅法
    public abstract void send(String message, Player player);
}

2. 具体中介者

// 具体中介者
public class ConcreteMediator extends Mediator {
    private List<Colleague> colleagues = new ArrayList<>();

    public void register((Colleague colleague) {
        colleagues.add(colleague);
    }

    @Override
    public void send(String message, Colleague colleague) {
        for (Colleague c : colleagues) {
            // 排除发送消息的同事对象
            if (c != colleague) {
                c.receive(message);
            }
        }
    }
}

3. 同事对象

// 同事对象
abstract class Colleague {
    protected Mediator mediator;
    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }
    // 发送消息
    public abstract void send(String message);
    // 接收消息
    public abstract void receive(String message);
}

4. 具体同事对象1

// 具体同事对象1
class ConcreteColleague1 extends Colleague {
    public ConcreteColleague1(Mediator mediator) {
        super(mediator);
    }
    @Override
    public void send(String message) {
        mediator.send(message, this);
    }
    @Override
    public void receive(String message) {
        System.out.println("ConcreteColleague1 received: " + message);
    }
}

5. 具体同事对象2

// 具体同事对象2
class ConcreteColleague2 extends Colleague {
    public ConcreteColleague2(Mediator mediator) {
        super(mediator);
    }
    @Override
    public void send(String message) {
        mediator.send(message, this);
    }
    @Override
    public void receive(String message) {
        System.out.println("ConcreteColleague2 received: " + message);
    }
}

6. 客户端

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file MediatorMode.hpp
* @brief 中介者模式
* @autor 写代码的小恐龙er
* @date 2024/01/18
*/

// 客户端
public class Main{
    public static void main(String[] args) {
    // 创建中介者
    Mediator mediator = new ConcreteMediator();
    // 创建同事对象
    Colleague colleague1 = new ConcreteColleague1(mediator);
    Colleague colleague2 = new ConcreteColleague2(mediator);
    // 注册同事对象到中介者
    mediator.register(colleague1);
    mediator.register(colleague2);
    // 同事对象之间发送消息
    colleague1.send("Hello from Colleague1!");
    colleague2.send("Hi from Colleague2!");
    }
}

【使用场景】

        中介者模式使得同事对象不需要知道彼此的细节,只需要与中介者进⾏通信,简化了系统的复杂度,也降低了各对象之间的耦合度,但是这也会使得中介者对象变得过于庞⼤和复杂,如果中介者对象出现问题,整个系统可能会受到影响。中介者模式适⽤于当系统对象之间存在复杂的交互关系或者系统需要在不同对象之间进⾏灵活的通信时使⽤,可以使得问题简化,


【C++编码部分】

1. 题目描述

        小明正在设计一个简单的多人聊天室系统,有多个用户和一个聊天室中介者,用户通过中介者进行聊天,请你帮他完成这个系统的设计。

2. 输入描述

        第一行包括一个整数N,表示用户的数量(1 <= N <= 100) 第二行是N个用户,比如User1 User2 User3,用空格分隔 第三行开始,每行包含两个字符串,表示消息的发出者和消息内容,用空格分隔;

3. 输出描述

        对于每个用户,输出一行,包含该用户收到的所有消息内容。

4. C++编码

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file MediatorMode.hpp
* @brief 中介者模式
* @autor 写代码的小恐龙er
* @date 2024/01/18
*/

#include <iostream>
#include <string>
#include <vector>
#include <map>

using namespace std;

// 前置声明

// 抽象中介者类 -- 定义中介者的接⼝,⽤于各个具体同事对象之间的通信
class ChatRoomMediator;
// 具体中介者类 -- 实现抽象中介者接⼝,负责协调各个具体同事对象的交互关系
class ChatRoomMediatorImpl;
// 抽象同事类 -- 定义同事类的接⼝,维护⼀个对中介者对象的引⽤,⽤于通信
class ChatUser;
// 具体同事类 -- 实现抽象同事类接⼝,每个具体同事类只知道⾃⼰的⾏为
class ConcreteChatUser;

// 类的定义

// 抽象中介者类
class ChatRoomMediator
{
// 成员接口函数
public:
    // 获取所有的同事类
    virtual std::map<string, ChatUser*> GetUsers() = 0;
    // 添加同事至中介类
    virtual void AddUser(ChatUser *user) = 0;
    // 中介者发送信息 至其他的所有用户
    virtual void SendMessage(string sender, string message) = 0;
    
};

// 抽象同事类 -- 接口
class ChatUser
{
// 成员函数接口
public:    
    // 获取当前的同事姓名
    virtual string GetName() = 0;
    
    // 发送信息至其他人 通过 中介者来代理
    virtual void SendMessage(string message) = 0;
    
    // 接收信息函数接口
    virtual void ReceiveMessage(string sender, string message) = 0;
    
    // 获取所有的信息集
    virtual std::vector<string> GetAllMessages() = 0;
    
    // 将接收到的信息存放至信息集中
protected:
    virtual void AddRecvMessageIntoVec(string message) = 0;
    
};

// 具体中介者类 
class ChatRoomMediatorImpl : public ChatRoomMediator
{
// 成员数据
private:
    std::map <string, ChatUser*> _chatUsers;
// 成员函数接口
public:
    // 获取所有的同事类 重载
    std::map<string, ChatUser*> GetUsers() override{
        return _chatUsers;
    }
    // 添加同事至中介类 重载
    void AddUser(ChatUser *user) override{
        _chatUsers.insert(std::pair<string, ChatUser*>(user->GetName(), user));
    }
    // 中介者发送信息 至其他的所有用户 函数重载
    void SendMessage(string sender, string message) override{
        for(map<string, ChatUser*>::iterator it = _chatUsers.begin(); it != _chatUsers.end(); it++){
            if(it->first != sender){
                it->second->ReceiveMessage(sender, message);
            }
        }
    }
};

// 具体同事类 
class ConcreteChatUser : public ChatUser
{
// 成员数据
private:
    // 用户姓名
    string _userName;
    // 中介者
    ChatRoomMediator * _mediator;
    // 所有接收到的信息
    std::vector<string> _recvMessages;
// 成员函数接口    
public:
    ConcreteChatUser(string name, ChatRoomMediator *mediator) { 
        this->_userName = name;
        this->_mediator = mediator;
        this->_mediator->AddUser(this);
    }
        // 获取当前的同事姓名
    string GetName() override {
        return _userName;
    }
    
    // 发送信息至其他人 通过 中介者来代理
    void SendMessage(string message) override {
        // 通过中介者去发送信息
        _mediator->SendMessage(_userName, message);
    }
    
    // 接收信息函数接口
    void ReceiveMessage(string sender, string message) override{
        string messages = _userName + " received: " + message;
        std::cout << messages << endl;
    }
    
    // 获取所有的信息集
    std::vector<string> GetAllMessages() override {
        return _recvMessages;
    }
    
    // 将接收到的信息存放至信息集中
protected:
    void AddRecvMessageIntoVec(string message) override{
        _recvMessages.push_back(message);
    }
};


int main()
{
    // 用户数量
    int userNum = 0;
    std::cin >> userNum;
    // 保存所有的用户
    std::vector<string> usersV;
    usersV.resize(userNum);
    
    for(int i = 0; i < userNum; i++){
        std::cin >> usersV[i];
    }
    
    // 抽象中介者
    ChatRoomMediator *mediator = new ChatRoomMediatorImpl();
    // 抽象用户类
    ChatUser *user = nullptr;
    // 在中介者类中添加所有的用户类
    // 遍历
    for(int i = 0; i < userNum; i++){
        // 构造具体的用户类
        user = new ConcreteChatUser(usersV[i], mediator);
    }
    // 此时已经在中介者类中添加了所有的用户
    
    // 遍历 去发送信息
    for(int i = 0; i < userNum; i++){
        // 获取发送者 和 消息
        string senderName = "";
        string sendMessage = "";
        // 输入
        std:: cin >> senderName >> sendMessage;
        // 用户通过中介者去发送消息
        mediator->SendMessage(senderName, sendMessage);
    }
    
    
    // 析构
    if(user != nullptr){
        delete user;
        user = nullptr;
    }
    delete mediator;
    mediator = nullptr;
    return 0;
    
}



【扩展:和代理模式的区别】

        中介者模式(Mediator Pattern)和代理模式(Proxy Pattern) 在某些表述上有些类似,但是他们是完全不同的两个设计模式,中介者模式的⽬的是降低系统中各个对象之间的直接耦合,通过引⼊⼀个中介者对象,使对象之间的通信集中在中介者上。而在代理模式中,客户端通过代理与⽬标对象进⾏通信。代理可以在调⽤⽬标对象的⽅法前后进⾏⼀些额外的操作,其⽬的是控制对对象的访问,它们分别解决了不同类型的问题。


......

To be continued.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/333546.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TCO-AF488,AF488-反式环辛烯,一种明亮的绿色荧光染料

文章关键词&#xff1a;AF488 TCO&#xff0c;Alexa Fluor TCO&#xff0c;TCO AF488&#xff0c;AF488 反式环辛烯 一、基本信息 产品简介&#xff1a;AF488 TCO&#xff0c;这是一款独特的荧光染料&#xff0c;以其鲜明的绿色光华吸引了众人的目光。在成像和流式细胞术中&a…

云HIS为连锁医院机构提供统一医院管理解决方案

云HIS重建统一的信息架构体系&#xff0c;重构管理服务流程&#xff0c;重造病人服务环境&#xff0c;向不同类型的医疗机构提供SaaS化HIS服务解决方案。 云HIS优势 1、云端数据优势 在传统的HIS模式里&#xff0c;数据存于医院本身的服务器机组&#xff0c;一旦发生故障&…

docker-compose安装mongodb

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 早上醒来的第一件事情就是摸了一下手机&#xff0c;看了一下微信相关的技术推文&#xff0c;给我推荐了一篇…

SpringBoot Redis入门(四)——Redis单机、哨兵、集群模式

单机模式&#xff1a;单台缓存服务器&#xff0c;开发、测试环境下使用&#xff1b;哨兵模式&#xff1a;主-从模式&#xff0c;提高缓存服务器的高可用和安全性。所有缓存的数据在每个节点上都一致。每个节点添加监听器&#xff0c;不断监听节点可用状态&#xff0c;一旦主节点…

three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera</title><script src"ThreeJS/three.js"></script><script src&qu…

服务器数据恢复—OceanStor存储raid5热备盘同步数据失败的数据恢复案例

服务器数据恢复环境&#xff1a; 华为OceanStor某型号存储&#xff0c;存储内有一组由24块硬盘组建的raid5阵列&#xff0c;配置1块热备盘。 服务器故障&#xff1a; 该存储raid5阵列中有一块硬盘离线&#xff0c;热备盘自动激活并开始同步数据&#xff0c;在热备盘同步数据的…

【北亚企安数据恢复】RAIDZ多块磁盘离线导致服务器崩溃的数据恢复案例

服务器数据恢复环境&#xff1a; ORACLE SUN ZFS某型号存储&#xff0c;共40块磁盘组建存储池&#xff0c;其中的36块磁盘分为三组&#xff0c;每组12块&#xff0c;单个组使用ZFS特有的RAIDZ管理所有磁盘&#xff0c;RAIDZ级别为2&#xff1b;另外的4块磁盘作为全局热备。存储…

关于 overflow 滚动条(滑动条)配置,简单使用的案例和案例代码

运行环境&#xff1a; Google Chrome 浏览器 前言&#xff1a; 滚动条的样式在CSS中属于伪元素&#xff08;pseudo-element&#xff09;&#xff0c;滚动条的样式则需要通过使用::-webkit-scrollbar 伪元素来定义。 滚动条(滑动条)的区域内包含三个基本部分&#xff0c;轨道…

视频智能识别周界入侵检测AI智能分析网关V4如何配置ONVIF摄像机接入

AI边缘计算智能分析网关V4性能高、功耗低、检测速度快&#xff0c;易安装、易维护&#xff0c;硬件内置了近40种AI算法模型&#xff0c;支持对接入的视频图像进行人、车、物、行为等实时检测分析&#xff0c;上报识别结果&#xff0c;并能进行语音告警播放。算法可按需组合、按…

K8S Informer机制原理解读 | 架构设计

在Kubernetes系统中&#xff0c;组件之间通过HTTP协议进行通信&#xff0c;在不依赖任何中间件的情况下需要保证消息的实时性、可靠性、顺序性等。那么Kubernetes是如何做到的呢&#xff1f;答案就是Informer机制。Kubernetes的其他组件都是通过client-go的Informer机制与Kuber…

12- OpenCV:算子(Sobel和Laplance) 和Canny边缘检测 详解

目录 一、Sobel算子 1、卷积应用-图像边缘提取 2、Sobel算子&#xff08;索贝尔算子&#xff09; 3、相关的API&#xff08;代码例子&#xff09; 二、Laplance算子 1、理论 2、API使用&#xff08;代码例子&#xff09; 三、Canny边缘检测 1、Canny算法介绍 2、API使…

每周一算法:数独游戏

题目链接 数独游戏 题目描述 数独是根据 9 9 9 \times 9 99 盘面上的已知数字&#xff0c;推理出所有剩余空格的数字&#xff0c;并满足每一行、每一列、每一个粗线宫内的数字均含 1 − 9 1 - 9 1−9 &#xff0c;不重复。每一道合格的数独谜题都有且仅有唯一答案&#x…

基于网络爬虫的天气数据分析

二、网络爬虫设计 网络爬虫原理 网络爬虫是一种自动化程序&#xff0c;用于从互联网上获取数据。其工作原理可以分为以下几个步骤&#xff1a; 定义起始点&#xff1a;网络爬虫首先需要定义一个或多个起始点&#xff08;URL&#xff09;&#xff0c;从这些起始点开始抓取数据…

中国IT产经新闻:AI人工智对就业产生影响但既是挑战也是机遇

近日国际权威人士表示&#xff0c;人工智能AI将影响全球近40%的就业岗位&#xff0c;其中相对新兴市场和低收入国家而言&#xff0c;发达经济体可能受到的冲击更大&#xff01;此言一出迅速应发了关于人工智能将对就业产生影响的大讨论&#xff01; 我们都知道随着科技的飞速发…

美摄视频SDK的HDR格式编辑方案

在当今的视觉媒体时代&#xff0c;高动态范围&#xff08;HDR&#xff09;技术已成为高质量视频内容的标配。为了满足企业对高效、高质量视频处理的需求&#xff0c;美摄科技推出了业界领先的视频SDK&#xff0c;全面支持多种HDR标准的图像视频进行处理。 一、核心优势 HDR全…

微信内测“听一听” 音乐音频业务提至一级入口;美团 AI 平台视觉中心负责人魏晓林离职;腾讯视频生成模型 VideoCrafter2;广州房价连跌12个月

今日精选 • 微信内测“听一听” 音乐音频业务提至一级入口• 美团 AI 平台视觉中心负责人魏晓林离职• 腾讯推出视频生成模型 VideoCrafter2&#xff0c;• 广州房价连跌12个月 投融资与企业动态 • TikTok 越南推出 Thu Duc Market 在线销售渠道• 亚马逊将在五年内在日本…

本地MinIO存储服务通过Java程序结合Cpolar内网穿透进行远程连接

文章目录 前言1. 创建Buckets和Access Keys2. Linux 安装Cpolar3. 创建连接MinIO服务公网地址4. 远程调用MinIO服务小结5. 固定连接TCP公网地址6. 固定地址连接测试 前言 MinIO是一款高性能、分布式的对象存储系统&#xff0c;它可以100%的运行在标准硬件上&#xff0c;即X86等…

深度学习模型之yolov8实例分割模型TesorRT部署-python版本

1 模型转换 从github上下载官方yolov8版本&#xff0c;当前使用的版本是2023年9月份更新的版本&#xff0c;作者一直在更新。官网地址 2 加载模型 模型的训练和测试在官方文档上&#xff0c;有详细的说明&#xff0c;yolov8中文文档这里不做过多说明&#xff0c;v8现在训练是…

自动化测试框架有哪些?

前言 自动化测试常用的Python框架有哪些&#xff1f;常用的框架有Robot Framework、Pytest、UnitTest/PyUnit、Behave、Lettuce。Pytest、Robot Framework和UnitTest主要用于功能与单元测试&#xff0c;Lettuce和Behave仅适用于行为驱动测试。 一、Robot Framework Python测…