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);}@Overridepublic 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);}@Overridepublic void send(String message) {mediator.send(message, this);}@Overridepublic void receive(String message) {System.out.println("ConcreteColleague1 received: " + message);}
}

5. 具体同事对象2

// 具体同事对象2
class ConcreteColleague2 extends Colleague {public ConcreteColleague2(Mediator mediator) {super(mediator);}@Overridepublic void send(String message) {mediator.send(message, this);}@Overridepublic 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.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 面向对象绘图(Matplotlib篇-16)

Python 面向对象绘图(Matplotlib篇-16)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

TQ8WS-acid,Tide Quencher 8WS-酸,可用来研究荧光物质的激发态

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;Tide Quencher8WS acid&#xff0c;TQ8WS acid&#xff0c;Tide Quencher 8WS 酸 &#xff0c;TQ8WS 酸&#xff0c;Tide Quencher 8WS-酸&#xff0c;TQ8WS-酸 一、基本信息 产品简介&#xff1a;The fluorescence…

牛客.KY11二叉树遍历、 LeetCode104.二叉树的最大深度 ,110平衡二叉树

二叉树实操小练习~这里对二叉树的遍历要有一定的理解&#xff0c;如果还不熟悉的小伙伴可以看看我的这篇博客&#xff1a;数据结构——二叉树&#xff08;先序、中序、后序及层次四种遍历&#xff08;C语言版&#xff09;&#xff09;超详细~ (✧∇✧) Q_Q-CSDN博客 牛客.KY11二…

文档翻译网站有哪些?这些工具高效翻译

文档翻译网站有哪些&#xff1f;随着全球化的加速&#xff0c;跨语言沟通变得越来越重要。然而&#xff0c;语言差异常常成为我们与世界各地人们交流的障碍。为了解决这个问题&#xff0c;文档翻译软件应运而生。今天&#xff0c;我们就来介绍一些受欢迎的文档翻译软件&#xf…

【Docker】安装nacos以及实现负载均衡

&#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Docker的相关操作吧 目录 &#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 前言 一.nacos单个部署 1.镜像拉取 …

4.C++类和对象

深拷贝和浅拷贝的简单理解&#xff1a;

提纲框架写作方法

论文提纲 论文提纲的意义 有利于检查构思有利于调整修改和写作 拟定提纲的目的 拟标题写总论点做总安排&#xff1a;几个方面&#xff0c;什么顺序做下位论点&#xff1a;每个项目的下位论点&#xff0c;直到段一级&#xff0c;写段的论点句考虑各段安排&#xff0c;把材料…

2024 前端高频面试题之 HTML/CSS 篇

【前言】随着市场的逐渐恶劣&#xff0c;通过总结面试题的方式来帮助更多的coder&#xff0c;也是记录自己的学习过程&#xff0c;温故而知新。欢迎各位同胞大大点评补充~ 前端面试题之 HTML/CSS 篇 1、HTML 语义化&#xff1f;2、块级元素&内联样式3、盒子模型的理解&…

机器学习:holdout法(Python)

import pandas as pd import numpy as np from sklearn.preprocessing import LabelEncoder, StandardScaler # 类别标签编码&#xff0c;标准化处理 from sklearn.decomposition import PCA # 主成分分析 import matplotlib.pyplot as plt from sklearn.model_selection impor…

springboot 原理分析之自动配置

一、Condition Condition 是在 Spring 4.0 增加的条件判断功能&#xff0c;通过这个可以功能可以实现选择性的创建 Bean 操作。比如说&#xff0c;只有满足某一个条件才能创建这个 Bean&#xff0c;否则就不创建。 SpringBoot 是如何知道要创建哪个 Bean 的&#xff1f;比如 Sp…

openGauss:准备知识1【IP地址/SSH协议/PuTTY安装和使用】

最近研究在openEuler 22.03 LTS上使用openGauss数据库。如果想要远端访问服务器&#xff0c;那么就先要了解IP地址、SSH协议等内容。 IP代表“Internet Protocol”&#xff0c;是一种网络协议&#xff0c;它定义了计算机在网络上的地址和数据传输方式。简言之&#xff0c;可以…

JAVA正则表达式第二个作用:爬取

目录 本地数据爬取&#xff1a; 本地爬取练习&#xff1a; 网络爬取&#xff1a; ----- 以下为均本地数据爬取&#xff1a; 带条件爬取 贪婪爬取和非贪婪爬取&#xff1a; 例题 1&#xff1a;使获取 1 为不贪婪 *例题 2&#xff1a;使获取 0、1 都为不贪婪 之前介绍了正…

【数据结构】- 单链表

先创建好SList.c、Test.c两个源文件和SList.h一个头文件。 SList.c和Test.c一样 SList.h 文件 在SList.h加上 1.单链表打印 SList.h SList.c 思路&#xff1a; 逻辑图&#xff08;之后经常用到&#xff09;&#xff1a; 物理图&#xff1a; 为了方便运行Test.c中的运行还要在…

链表中倒数最后k个结点

链表中倒数最后k个结点 链表中倒数最后k个结点_牛客题霸_牛客网输入一个长度为 n 的链表&#xff0c;设链表中的元素的值为 ai &#xff0c;返回该链表中倒数第k个节点。。题目来自【牛客题霸】https://www.nowcoder.com/practice/886370fe658f41b498d40fb34ae76ff9 描述 输…

RNN:Recurrent Neural Network(上)

目录 1 为什么提出 RNN 1.1 什么是 Slot Filling 1.2 为什么 FFN 做不好 Slot Filling 1.3 为什么 RNN 能做好 Slot Filling 2 RNN 的整体结构 3 更高级的 RNN 结构 3.1 Deep RNN 3.2 Elman Network & Jordan Network 3.3 Bidirectional RNN 原视频&…

怎么样的布局是符合可制造性的PCB布局?

满足可制造性、可装配性、可维修性要求&#xff0c;方便调试的时候于检测和返修&#xff0c;能够方便的拆卸器件&#xff1a; 1&#xff09;极性器件的方向不要超过2种&#xff0c;最好都进行统一方向等要求&#xff0c;如图1-1所示&#xff1b; 图1-1 极性器件方向统一摆放 2…

k8s的坑,从这里开始

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 以前刚接触k8s时踩了不少坑&#xff0c;比如这些&#xff1a; 问题1 1、在master节点使用kubectl命令时&#xff0c;报错&…

阿里云云原生弹性方案:用弹性解决集群资源利用率难题

作者&#xff1a;赫曦 随着上云的认知更加普遍&#xff0c;我们发现除了以往占大部分的互联网类型的客户&#xff0c;一些传统的企业&#xff0c;一些制造类的和工业型企业客户也都开始使用云原生的方式去做 IT 架构的转型&#xff0c;提高集群资源使用率也成为企业上云的一致…

20. 从零用Rust编写正反向代理,四层反向代理stream(tcp与udp)实现

wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器&#xff0c;四层TCP/UDP转发&#xff0c;内网穿透&#xff0c;后续将实现websocket代理等&#xff0c;会将实现过程分享出来&#xff0c;感兴趣的可以一起造个轮子 项目地址 gite: https:…