对中介者模式的理解

news/2024/5/24 4:26:28

目录

  • 一、场景
    • 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.mrgr.cn/p/24332834

相关文章

【数据库系统工程师】2024年5月考前最后冲刺指南

一、备考关键&#xff1a; 高效率的备考方式&#xff1a;多轮迭代学习 △ 基础阶段 △ 大面积撒网(60%) 略读&#xff0d;> 做题 &#xff0d;> 回顾 &#xff0d;> 精读 △ 积累阶段 △ 有针对性的突破(30%) 完成所有章节之后&#xff0c;进行真题测试&#x…

【Shell】正则表达式的操作实例

正则表达式是一个描述一组字符串的模式 是由普通字符和元字符组成的字符集&#xff0c;而这个字符集匹配&#xff08;或指定&#xff09;一个模式。 正则表达式的操作实例 &#xff08;一&#xff09;概述1.定义2.作用3.类型 &#xff08;二&#xff09;字符串匹配实例&#xf…

Windows2016系统禁止关闭系统自动更新教程

目录 1.输入cmd--适合系统2016版本2.输入sconfig&#xff0c;然后按回车键3.输入5&#xff0c;然后按回车键4.示例需要设置为手动更新&#xff0c;即输入M&#xff0c;然后按回车键 1.输入cmd–适合系统2016版本 2.输入sconfig&#xff0c;然后按回车键 3.输入5&#xff0c;然后…

使用Gin编写Web API项目并自动化文档

最近需要使用Go写一个Web API项目&#xff0c;可以使用Beego与Gin来写此类项目&#xff0c;前文使用Beego创建API项目并自动化文档介绍了使用Beego来创建的Web API项目并自动化文档的方法。本文就介绍一下使用Gin来编写Web API项目并自动化文档。 一、创建项目 在创建Beego项…

基于百川大语言模型的RSS新闻过滤应用【云服务器+公网网页,随时随地看自己DIY订阅的新闻内容】

背景 目前从公众号、新闻媒体上获得的新闻信息,都是经过算法过滤推荐的,很多时候会感到内容的重复性和低质量,因为他们也要考虑到自己的利益,并非完全考虑用户想要的、对用户有价值的信息。这时,如果要获取自己认为重要的信息,定制化开发自己的筛选算法更好。 效果 素材…

PWM

PWMPWM1. 什么是PWM? 2. 面积等效原理2.1. 什么是面积等效原理? 2.2. 面积等效原理的理解3. 相关概念3.1. 周期和频率 3.2. 占空比4. 总结 参考链接 others1. 什么是PWM? PWM是Pulse Width Modulation的缩写,中文是脉冲宽度调制。 是利用微处理器的数字输出来对模拟电路进行…

ComfyUI 介绍及入门

介绍 ComfyUI 是一种用户界面&#xff0c;它采用了基于节点的流程设计&#xff0c;用于操作一种名为 Stable Diffusion 的技术。这种设计允许用户通过自定义流程来实现更精确的工作流程&#xff0c;并确保结果的可重复性。在 ComfyUI 中&#xff0c;每个模块都承担着特定的任务…

基于MetaGPT的智能体理论与实践-Task01

Task01: MetaGPT环境配置 学习教程&#xff1a;https://github.com/datawhalechina/hugging-multi-agent 1 环境准备 1.1 安装python3.9 通过&#xff1a;python3 --version, 查看此python版本为3.10.3 1.2 下载MetaGPT 开始&#xff0c;借用清华镜像&#xff0c;拉取…

Linux环境Redis部署

Redis部署 Redis是一个高性能的开源键值存储系统&#xff0c;它主要基于内存操作&#xff0c;但也支持数据的持久化。与其他数据库相比&#xff0c;Redis的主要优势在于它的高性能、丰富的数据结构和原生的持久化能力。Redis不仅提供了类似的功能&#xff0c;还增加了持久化和…

外卖系统微信小程序支付

微信小程序支付时序图 其中第9.步骤就是微信小程序前端调用wx.requestPayment

02--JS02--高级

JavaScript02: 进阶 一. 变量声明 1.1 变量提升 // 以下代码,或多或少会有些问题的 function fn(){console.log(name);var name = 大马猴; }fn()// 问题: name变量先使用,再定义 这么写代码,在其他语言里. 绝对是不允许的 但是在js里,不但允许,还能执行,为什么呢? 因…

20.接口自动化-Git

1、Git和SVN–版本控制系统 远程服务出问题后&#xff0c;可以先提交commit到本地仓库&#xff0c;之后再提交push远程仓库 git有clone Git环境组成部分 常用Git代码仓库服务-远程仓库 GitHub-服务器在国外&#xff0c;慢 GitLab-开源&#xff0c;可以在自己服务器搭建&…

基于Springboot的实习生管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的实习生管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&a…

库的移植

库移植的步骤从官网下载需要移植的库的源码包。解压压缩包,解压后找到自述文件README,打开README了解libjpeg库的使用规则!根据源码包中的install.txt的文本,学习libjpeg库的移植和安装的步骤,移植libjpeg的步骤分为三步:配置(./configure) + 编译(make) + 安装(make in…

【算法】并查集

并查集是一种树形的数据结构&#xff0c;通常可以用于高效的合并多个集合和查询两个数是否属于同一个集合的情况。 其原理在于&#xff0c;把每个集合变成一棵树&#xff0c;树根的值就是整个集合的编号&#xff0c;通过查找两个数所在树根是否相同即可判断是否在同一个集合&a…

苍穹外卖Day06笔记(复习了jwt的加密解密和传递)

疯玩了一个月&#xff0c;效率好低&#xff0c;今天开始捡起来苍穹外卖~ 1. 为什么不需要单独引入HttpClient的dependency&#xff1f; 因为我们在sky-common的pom.xml中已经引入了aliyun-sdk-oss的依赖&#xff0c;而这个依赖低层就引入了httpclinet的依赖&#xff0c;根据依…

2022——蓝桥杯十三届2022国赛大学B组真题

问题分析 看到这个问题的同学很容易想到用十层循环暴力计算&#xff0c;反正是道填空题&#xff0c;一直算总能算得出来的&#xff0c;还有些同学可能觉得十层循环太恐怖了&#xff0c;写成回溯更简洁一点。像下面这样 #include <bits/stdc.h> using namespace std; in…

【SRC实战】前端脱敏信息泄露

挖个洞先 https://mp.weixin.qq.com/s/xnCQQCAneT21vYH8Q3OCpw “ 以下漏洞均为实验靶场&#xff0c;如有雷同&#xff0c;纯属巧合 ” 01 — 漏洞证明 一、前端脱敏&#xff0c;请求包泄露明文 “ 前端脱敏处理&#xff0c;请求包是否存在泄露&#xff1f; ” 1、获取验…

uniapp wifi调试

adb 版本大于 30无线调试 -> 使用配对码配对设备终端输入命令: adb pair ip地址:port端口 (替换为对应的ip和端口),回车后,继续输入WLAN配对码成功提示 Successfully paired to 192.168.137.21:38583 [guid=adb-xxxxxxx]最后 adb connect ip地址:port端口 (替换为对应的i…

水库大坝安全监测预警系统解决方案介绍

一、方案背景 随着社会的快速发展&#xff0c;水库大坝作为重要的水利工程设施&#xff0c;承载着防洪、灌溉、发电等多重功能。然而水库大坝的安全问题也日益凸显&#xff0c;一旦发生事故&#xff0c;后果将不堪设想&#xff0c;因此&#xff0c;建立一套高效、准确的水库大…