对中介者模式的理解

目录

  • 一、场景
    • 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.hqwc.cn/news/696697.html

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

相关文章

Spring框架概述

目录 1. Spring框架的起源 2. Spring框架的构成 3. Spring的发展历程 4. Spring的开发环境 4.1. Maven安装与配置 &#xff08;1&#xff09;Maven的下载与安装 &#xff08;2&#xff09;配置Maven的环境变量 &#xff08;3&#xff09;本地仓库的配置 &#xff08;4…

STM32(GPIO)

GPIO简介 GPIO&#xff08;General Purpose Input Output&#xff09;通用输入输出口 引脚电平&#xff1a;0V~3.3V&#xff0c;部分引脚可容忍5V 输出模式下可控制端口输出高低电平&#xff0c;用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等 输入模式下可读取端口的高低电…

企业员工出行如何轻松搞定行程变更?

对于业务部门而言&#xff0c;由于工作中需要不时地面临紧急和重要的任务&#xff0c;行程变更已经成为了常态&#xff0c;往往牵一发而动全身。 过去&#xff0c;如果业务量大、行程变更得频繁&#xff0c;员工需要重复提交申请单或多次口头通知。这不仅增加沟通成本&#xff…

山东济南中国姓名学第一人颜廷利:全球知名哲学家思想家

颜廷利教授是一位在全球华人中享有崇高声誉的学者&#xff0c;他的影响力深远而广泛。他的教育和哲学思想在全球范围内产生了深远的影响&#xff0c;因此&#xff0c;宁夏银川口碑最好最靠谱的专业权威著名起名专家大师的师傅颜廷利教授被公认为21世纪影响世界的当代教育家代表…

3.整数运算

系列文章目录 信息的表示和处理 : Information Storage&#xff08;信息存储&#xff09;Integer Representation&#xff08;整数表示&#xff09;Integer Arithmetic&#xff08;整数运算&#xff09;Floating Point&#xff08;浮点数&#xff09; 文章目录 系列文章目录前…

国际护士节庆祝活动向媒体投稿有方法很轻松

作为一名医院职工,我肩负着医院对外信息宣传的重任。在国际护士节这个特殊的日子里,我们医院举办了一系列庆祝活动,以表彰护士们的辛勤付出和无私奉献。然而,在将这些活动信息投稿至媒体的过程中,我最初却遭遇了诸多挑战。 起初,我采用传统的邮箱投稿方式,将精心撰写的稿件发送…

小程序常用组件

小程序常用组件 1.组件的定义2.常用组件3.引入外部字体图标库4.组件样式5.示例代码 1.组件的定义 组件就是指微信定义的具有特殊功能的标签&#xff0c;在wxml中只能使用微信定义的标签。 2.常用组件 <view>&#xff1a;用于页面布局的块级组件&#xff0c;类似于html中的…

基础ArkTS组件:帧动画,内置动画组件,跑马灯组件(HarmonyOS学习第三课【3.6】)

帧动画 帧动画也叫序列帧动画&#xff0c;其原理就是在时间轴的每帧上逐帧绘制不同的内容&#xff0c;使其连续播放而成动画。ArkUI开发框架提供了 ImageAnimator 组件实现帧动画能力&#xff0c;本节笔者介绍一下 ImageAnimator 组件的简单使用。 官方文献 说明 该组件从A…

基于springboot+vue+Mysql的音乐翻唱与分享平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

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

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

python内置函数exec()和eval()区别

在Python中&#xff0c;eval() 和 exec() 都是内置函数&#xff0c;用于执行存储在字符串或对象中的Python代码&#xff0c;但它们之间也有一些区别。 eval() 语法&#xff1a;eval(expression, globalsNone, localsNone) expression&#xff1a;需要求值的字符串表达式。可…

ohmyzsh的安装过程中失败拒绝连接问题的解决

1.打开官网Oh My Zsh - a delightful & open source framework for Zsh 在官网能看到下面的界面 有这两种自动安装的方式 个人本次选择的是: wget https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O - 1.打开终端输入安装的指令 sh -c "$(wget…