对中介者模式的理解

news2024/11/26 1:32:21

目录

  • 一、场景
    • 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;
    }

    @Override
    public void receive(String message) {
        System.out.println(name + " received: " + message);
    }

    @Override
    public 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<>();
    }

    @Override
    public 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.coloradmin.cn/o/1671638.html

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

相关文章

Postman基础功能-变量设置与使用

如果你因失去太阳而流泪&#xff0c;那你也将失去群星了。大家好&#xff0c;在 API 测试的广袤世界中&#xff0c;Postman 犹如一座闪耀的灯塔&#xff0c;为我们指引着前行的方向。而其中的全局变量、集合变量和环境变量&#xff0c;更是如同隐藏的宝藏&#xff0c;蕴含着巨大…

从3D模型到渲染:完整的流程指南---模大狮模型网

在当今数字化时代&#xff0c;3D模型和渲染技术在各个领域中扮演着至关重要的角色&#xff0c;从影视制作到建筑设计&#xff0c;从游戏开发到工程模拟。了解如何将3D模型转化为逼真的渲染图像是数字创意领域从业者的关键技能之一。本文将为您介绍从3D模型到渲染的完整流程&…

企业使用合同档案管理系统软件有什么好处

使用合同档案管理系统软件可以带来以下好处&#xff1a; 1. 提高效率&#xff1a;合同管理软件可以自动化合同流程&#xff0c;包括创建、审批、签署和归档等。通过自动化&#xff0c;可以节省大量时间和精力&#xff0c;提高工作效率。 2. 降低风险&#xff1a;玖拓档案合同管…

LVS + Keepalived 高可用群集

一、准备环境 主keepalived&#xff1a;172.168.1.11 lvs 备keepalived&#xff1a;172.168.1.12 lvs web1&#xff1a;172.168.1.13 web2&#xff1a;172.168.1.14 vip&#xff1a;172.168.1.100 客户机访问 关闭防火墙 二、配置 主keepalived 服务器 1. 安装…

给返修就能炫耀几年?16.4的高分,指标优秀,行业公认top 1顶刊!

本周投稿推荐 SSCI • 2区社科类&#xff0c;3.0-4.0&#xff08;社科均可&#xff09; EI • 计算机工程类&#xff08;接收广&#xff0c;录用极快&#xff09; SCI&EI • 4区生物医学类&#xff0c;1.5-2.0&#xff08;录用率99%&#xff09; • 1区工程类&#…

深入学习指针2

前言 hello,我又来了&#xff0c;今天有我继续带领大家深入的学习指针&#xff0c;通过上次的学习&#xff0c;我们已经了解到了指针的基本概念&#xff0c;指针如何使用&#xff0c;指针使用的益处&#xff0c;以及一些相关的概念&#xff0c;那今天我们就继续深入的学习&am…

JDK的串行收集器介绍与优化指南-01

JDK串行收集器概述 定义与背景 串行收集器&#xff08;Serial Collector&#xff09;是Java虚拟机&#xff08;JVM&#xff09;中的一种单线程垃圾收集器&#xff0c;它在垃圾收集过程中会暂停所有工作线程&#xff0c;直至收集完成。它适用于内存资源受限、对吞吐量要求不高…

MySQL 大量数据插入优化

效率最好的方式是&#xff1a;批量插入 开启事务。 1、数据批量插入相比数据逐条插入的运行效率得到极大提升&#xff1b; ## 批量插入 INSERT INTO table (field1, field12,...) VALUES (valuea1, valuea2,...), (valueb1, valueb2,...),...;当数据逐条插入时&#xff0c;每…

OFDM802.11a的FPGA实现(十四)data域的设计优化,挤掉axi协议传输中的气泡

原文链接&#xff08;相关文章合集&#xff09;&#xff1a;OFDM 802.11a的xilinx FPGA实现 目录 1.前言 2.data域的时序要求 3.Debug 1.前言 前面12篇文章详细讲述了&#xff0c;OFDM 802.11a发射部分data域的FPGA实现和验证&#xff0c;今天对data域的设计做一个总结。在…

升级! 测试萌新Python学习之连通数据库Pymsql增删改及封装(四)

pymysql 数据库概述python对数据库的增删改查pymysql核心操作事务事务操作pymysql工具类封装每日复习ChatGPT的回答 数据库概述 分类 关系型数据库: 安全 如, mysql oracle SQLite…database tables 行列 非关系型数据库: 高效 如, redis mongoDB…数据存储结构多样 键值对…

基于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;…

252 基于MATLAB的自适应差分阈值法检测心电信号的QRS波

基于MATLAB的自适应差分阈值法检测心电信号的QRS波&#xff0c;QRS波群反映左、右心室除极电位和时间的变化&#xff0c;第一个向下的波为Q波&#xff0c;向上的波为R波&#xff0c;接着向下的波是S波。通过GUI进行数据处理&#xff0c;展示心率和QRS。程序已调通&#xff0c;可…

geotrust dv通配符证书800

Geotrust是成立时间较久的正规CA认证机构&#xff0c;在过去的几十年间颁发了无数的SSL证书&#xff0c;这些SSL证书被各个开发者使用&#xff0c;受到大多数浏览器的信任。而Geotrust旗下的DV通配符证书因其广泛的应用范围受到了用户的青睐。今天就随SSL盾小编了解Geotrust旗下…

物联网设计竞赛_3_Jetson Nano连接摄像头

ls /dev/video* 查看是否有摄像头 camorama 开启摄像头 关闭摄像头用&#xff1a; ctr c结束进程 若有camorama被启动用ps aux 或者 ps aux l grep camorama 找到对应进程用 kill -9 <PID>杀死进程再启动 必要的时候也能重启系统再试试&#xff1a; shutdown -r …

Java中PriorityQueue的用途和性能深度剖析

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

出租车计价器设计与实现(论文 + 源码)

关于java出租车计价器设计与实现.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89304164 出租车计价器设计与实现 摘 要 在我国&#xff0c;出租车行业是八十年代初兴起的一项新兴行业&#xff0c;随着出租车的产生&#xff0c;计价器也就应运而生。但当时在全…

springboot 整合阿里云短信服务

官方sdk示例地址 依赖引入 <!-- https://mvnrepository.com/artifact/com.aliyun/dysmsapi20170525 --><dependency><groupId>com.aliyun</groupId><artifactId>dysmsapi20170525</artifactId><version>2.0.23</version><…

我的 OpenLiteSpeed 从开始到放弃之经历

昨晚下定决心放弃 OpenLiteSpeed 了&#xff0c;从开始到放弃历时七天。总结下来放弃 OpenLiteSpeed 主要是实在不适合明月当前的需要&#xff0c;用起来不是锦上添花而是个累赘了都&#xff0c;今天明月就给大家总结分享一下这次 OpenLiteSpeed 从开始到放弃的经历。 一、Ngin…

福建医疗器械展/2024厦门国际医疗器械展览会重磅来袭

2024中国&#xff08;厦门&#xff09;国际医疗器械展览会 时 间&#xff1a;2024年11月1-3日 November 1-3, 2024 地 点&#xff1a;厦门国际会展中心 Xiamen International Conference & Exhibition Center ​ ◆组织机构 主办单位&#xff1a; 中国技术市场协会医…

【QT】QT环境搭建

本专栏内容为&#xff1a;QT学习专栏 通过本专栏的深入学习&#xff0c;你可以了解并掌握QT。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;QT &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &#x1f339;&#x1f…