对中介者模式的理解

目录

  • 一、场景
    • 1、题目 【[来源](https://kamacoder.com/problempage.php?pid=1094)】
      • 1.1 题目描述
      • 1.2 输入描述
      • 1.3 输出描述
      • 1.4 输入示例
      • 1.5 输出示例
  • 二、不采用中介者设计模式
    • 1 代码
    • 2 问题
  • 三、中介者设计模式
    • 1 代码
    • 2 更好的例子
  • 四、个人思考

一、场景

  • 设计模式不是银弹,而是特定场景的参考解法。
  • 例如,在多人聊天室场景下,不采用中介者模式,系统会变得复杂。

1、题目 【来源】

1.1 题目描述

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

1.2 输入描述

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

1.3 输出描述

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

1.4 输入示例

3
User1 User2 User3
User1 Hello_All!
User2 Hi_User1!
User3 How_is_everyone?

1.5 输出示例

User2 received: Hello_All!
User3 received: Hello_All!
User1 received: Hi_User1!
User3 received: Hi_User1!
User1 received: How_is_everyone?
User2 received: How_is_everyone?

二、不采用中介者设计模式

1 代码

  • 将聊天室的人定义为User:
public class User {private List<User> friends;private String name;public User(String name) {this.name = name;friends = new ArrayList<>();}public void addFriend(User user) {friends.add(user);}public void sendMessage(String message) {friends.forEach(user -> user.receiveMessage(message));}private void receiveMessage(String message) {System.out.println(name + " received: " + message);}
}
  • 客户端:
public class Application {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);Map<String, User> userMap = new TreeMap<>();int n = scanner.nextInt();for (int i = 0; i < n; i++) {String name = scanner.next();User user = new User(name);userMap.put(name, user);}List<User> users = new ArrayList<>(userMap.values());users.stream().forEach(user -> {for (User friend : users) {if (!user.equals(friend)) {user.addFriend(friend);}}});for (int i = 0; i < n; i++) {String name = scanner.next();String message = scanner.next();userMap.get(name).sendMessage(message);}}
}

2 问题

  • 现在聊天室里就3个人,只要1个人发消息,其他人都能收到。如果有人退群了,或者有新朋友加群了,都需要重新维护关系:
List<User> users = new ArrayList<>(userMap.values());
users.stream().forEach(user -> {for (User friend : users) {if (!user.equals(friend)) {user.addFriend(friend);}}
});
  • 当一个实体(例如:User)状态变化时,会影响其他实体,不应该由实体本身来维护这种复杂关系。实体只需关心自己的状态变化即可。
    • 这就需要中介者设计模式。

三、中介者设计模式

1 代码

  • 用户:
public interface Colleague {void receive(String message);String gotName();
}public class User implements Colleague {private final String name;public User(String name) {this.name = name;}@Overridepublic void receive(String message) {System.out.println(name + " received: " + message);}@Overridepublic String gotName() {return name;}
}
  • 中介者:
public interface Mediator {void add(Colleague colleague);
}public class ChatRoom implements Mediator {private List<Colleague> colleagues;public ChatRoom() {this.colleagues = new ArrayList<>();}@Overridepublic void add(Colleague colleague) {colleagues.add(colleague);}public void send(String message, Colleague colleague) {colleagues.stream().filter(c -> !StringUtils.equals(c.gotName(), colleague.gotName())).forEach(c -> c.receive(message));}
}
  • 客户端:
public class Application {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);ChatRoom chatRoom = new ChatRoom();int n = scanner.nextInt();for (int i = 0; i < n; i++) {String name = scanner.next();chatRoom.add(new User(name));}for (int i = 0; i < n; i++) {String name = scanner.next();String message = scanner.next();chatRoom.send(message, new User(name));}}
}

2 更好的例子

  • 廖雪峰老师在介绍中介者模式时,举的例子更好:
    在这里插入图片描述
    • 多选框会影响Select All、Select None的按钮状态。
      • 例如,多选框勾选后,Select None按钮便会亮起: 在这里插入图片描述
    • 多选框不应该去关心Select None按钮的状态,这就需要中介者模式来处理了。
  • 多选框状态变化后,中介者“收到变化消息”,如果需要更改按钮的状态,则去更改状态。
  • 代码:
public class Mediator {// 引用UI组件:private List<JCheckBox> checkBoxList;private JButton selectAll;private JButton selectNone;private JButton selectInverse;public Mediator(List<JCheckBox> checkBoxList, JButton selectAll, JButton selectNone, JButton selectInverse) {......// 绑定事件:this.checkBoxList.forEach(checkBox -> {checkBox.addChangeListener(this::onCheckBoxChanged);});this.selectAll.addActionListener(this::onSelectAllClicked);this.selectNone.addActionListener(this::onSelectNoneClicked);this.selectInverse.addActionListener(this::onSelectInverseClicked);}// 当checkbox有变化时:public void onCheckBoxChanged(ChangeEvent event) {boolean allChecked = true;boolean allUnchecked = true;for (JCheckBox checkBox : checkBoxList) {if (checkBox.isSelected()) {allUnchecked = false;} else {allChecked = false;}}selectAll.setEnabled(!allChecked);selectNone.setEnabled(!allUnchecked);}// 当点击select all:public void onSelectAllClicked(ActionEvent event) {checkBoxList.forEach(checkBox -> checkBox.setSelected(true));selectAll.setEnabled(false);selectNone.setEnabled(true);}// 当点击select none:public void onSelectNoneClicked(ActionEvent event) {checkBoxList.forEach(checkBox -> checkBox.setSelected(false));selectAll.setEnabled(true);selectNone.setEnabled(false);}// 当点击select inverse:public void onSelectInverseClicked(ActionEvent event) {checkBoxList.forEach(checkBox -> checkBox.setSelected(!checkBox.isSelected()));onCheckBoxChanged(null);}
}

四、个人思考

  • 当我们对场景建模后发现,实体们呈现类似如下关系时:
    在这里插入图片描述
    • 我们就需要引入中介来统筹实体们的相互影响。
      • 实体1变化了,发消息给中介,中介收到后,去改变实体4和实体2的状态。
  • 中介者:
public interface Mediator {...
}public class xxx implements Mediator {...
}
  • 各种实体:
public interface Colleague {...
}public class yyy implements Colleague {...
}

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

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

相关文章

宝塔纯净版 7.6.0版本无需手机登录 [稳定版本/推荐]

下载地址&#xff1a;宝塔纯净版 7.6.0版本无需手机登录.zip 宝塔纯净版介绍 无需手机登录&#xff1a;不再有手机登录提示&#xff0c;或按照提示输入任意手机号密码即可模拟绑定&#xff1b; 安全&#xff1a;剥离了所有与宝塔官方的通信、上报、下发&#xff1b;并且不与…

有哪些网络兼职适合大学生参与?揭秘几个简单又实用的兼职机会

有哪些网络兼职适合大学生参与&#xff1f;揭秘几个简单又实用的兼职机会 对于大学生而言&#xff0c;除了专注于学业&#xff0c;利用空余时间参与一些网络兼职&#xff0c;不仅能锻炼个人技能&#xff0c;还能为未来的职业生涯积累宝贵的经验。想象一下&#xff0c;步入社会…

Linux-磁盘管理类实训

一、Linux分区和磁盘操作命令 &#xff08;1&#xff09;将系统内所有的分区&#xff08;文件系统&#xff09;列出来&#xff09; &#xff08;2&#xff09;将系统中所有特殊文件格式及名称都列出来 &#xff08;3&#xff09;将/bin下面的可以用的磁盘容量以易读的容量格式…

房屋出租管理系统需求分析及功能介绍

房屋租赁管理系统适用于写字楼、办公楼、厂区、园区、商城、公寓等商办商业不动产的租赁管理及租赁营销&#xff1b;提供资产管理&#xff0c;合同管理&#xff0c;租赁管理&#xff0c; 物业管理&#xff0c;门禁管理等一体化的运营管理平台&#xff0c;提高项目方管理运营效率…

OpenAI之Whisper实时语音分析转文字

1.安装ffmpeg 2.安装python3.11 3.安装whisper pip install whisper conda环境安装whisper conda install whisper 命令行安装openai-whisper pip install openai-whisper 设置环境变量 4.分析语音并输出(默认使用GPU计算&#xff0c;如果没有安装CUDA,请使用CPU) whisper …

吃透前端文件上传与文件相关操作

最近在学文件上传的操作,所以想把学习到东西写成一文章 这片文章是我以小白视角 慢慢学习并熟悉前端文件相关操作的流程总结出来的 前端文件上传 我首先想到是 <input type"file">选择文件</input>如果我们想限制上传文件的格式,大小或进行裁剪分片上传…

2024审计师报名流程图解❗报名时间汇总❗

2024年审计专业技术资格考试报名正在进行中 &#x1f50d;审计报名流程 一、考生注册 打开浏览器登录中国人事考试网进行【考生注册】&#xff0c;按照提示认真填写个人注册信息&#xff0c;确保个人信息真实、完整、准确&#xff0c;并上传已处理好的照片。 二、考生报名 1⃣考…

[C++核心编程-09]----C++类和对象之继承

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

C++进阶:哈希(1)

目录 1. 简介unordered_set与unordered_map2. 哈希表&#xff08;散列&#xff09;2.1 哈希表的引入2.2 闭散列的除留余数法2.2.1 前置知识补充与描述2.2.2 闭散列哈希表实现 2.3 开散列的哈希桶2.3.1 结构描述2.3.2 开散列哈希桶实现2.3.3 哈希桶的迭代器与key值处理仿函数 3.…

7B2 PRO主题5.4.2 免授权开心版源码 | WordPress主题

简介&#xff1a; B2 PRO 5.4.2 最新免授权版不再需要改hosts&#xff0c;和正版一样上传安装就可以激活。 直接在WordPress上传安装即可 点击下载

巴奴火锅翻车,杜中兵后悔暗讽海底捞

曾经喊出“服务不过度&#xff0c;样样都讲究”、内涵海底捞的巴奴火锅&#xff0c;又改回了2012年的广告语&#xff0c;试图重回“产品主义”。 巴奴火锅于2001年创立于河南安阳&#xff0c;彼时被视作火锅界的黑马。巴奴火锅创始人的杜中兵&#xff0c;坚信“产品主义”一定…

基于SpringBoot + Vue的学生宿舍课管理系统设计与实现+毕业论文(15000字)+开题报告

系统介绍 本系统包含管理员、宿管员、学生三个角色。 管理员&#xff1a;管理宿管员、管理学生、修改密码、维护个人信息。 宿管员&#xff1a;管理公寓资产、管理缴费信息、管理公共场所清理信息、管理日常事务信息、审核学生床位安排信息。 学生&#xff1a;查看公共场所清理…

【C++】 string类:应用与实践

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

ASP.NET Web Api 如何使用 Swagger 管理 API

前言 Swagger 是一个开源的框架&#xff0c;支持 OpenAPI 规范&#xff0c;可以根据 API 规范自动生成美观的、易于浏览的 API 文档页面&#xff0c;包括请求参数、响应示例等信息&#xff0c;并且&#xff0c;Swagger UI 提供了一个交互式的界面&#xff0c;可以帮助我们快速…

Java——多线程

一.多线程 1.什么是多线程 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程的实际运作单位 简单理解多线程就是应用软件中相互独立&#xff0c;可以同时运行的功能(也可以理解为人体内相互独立&#xff0c;但可以同时运行的器官⌓‿⌓) 我们…

如何用时尚新姿讲好中国品牌故事?

品牌建设在推动高质量发展中扮演了双重角色&#xff0c;既是高质量发展的重要“承载者”&#xff0c;也是强有力的“助推器”。5月10日-11日&#xff0c;中国时尚品牌URBAN REVIVO&#xff08;以下简称UR&#xff09;以中国品牌日为起点&#xff0c;联合天猫超级品牌日&#xf…

Linux提权--SUDO(CVE-2021-3156)Polkit(CVE-2021-4034)

免责声明:本文仅做技术学习与交流... 目录 SUDO(CVE-2021-3156) 影响版本 -判断&#xff1a; -利用&#xff1a; Polkit(CVE-2021-4034&#xff09; ​ -判断&#xff1a; -利用: 添加用户 SUDO(CVE-2021-3156) another: SUDO权限配置不当. 影响版本 由系统的内核和发…

【LAMMPS学习】八、基础知识(6.3)使用 LAMMPS GUI

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各种模拟。 …

西门子博途WINCC动画之旋转运动

概述 本例将介绍在西门子 TIA Portal HMI 中旋转运动动画的一种实现方法。本例以风机、搅拌器和传送带为例&#xff0c;按下启动按钮开始转动&#xff0c;按下停止按钮停止转动。 第1步&#xff1a; 添加 PLC 设备。​博途TIA/WINCC社区VX群 ​博途TIA/WINCC社区VX群 选择西…

PyQt5中的QGraphicsView()

文章目录 1. 简介2. 一个简单的示例2. 加载一幅图片3. 常用方法示例 1. 简介 QGraphicsView是PyQt5中用于显示图形场景的小部件&#xff0c;它提供了许多常用的方法来控制视图的行为和属性。下面是一些常用的QGraphicsView方法&#xff1a; setScene(scene): 设置要显示的场景…