中介者模式的理解和实践

一、中介者模式概述

        中介者模式(Mediator Pattern),也称为调解者模式或调停者模式,是一种行为设计模式。它的核心思想是通过引入一个中介者对象来封装一系列对象之间的交互,使得这些对象不必直接相互作用,从而达到松散耦合的效果。这种设计模式主要用于降低系统中对象之间的耦合度,提高系统的灵活性和可维护性。

        中介者模式定义了一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,并且可以独立地改变它们之间的交互。在这个模式中,各个对象不再直接相互引用和通信,而是通过中介者来进行间接通信。这样,不仅降低了对象之间的依赖关系,还简化了对象之间的交互逻辑。

 

二、中介者模式的结构

        中介者模式通常包含以下几个关键角色:

  1. 抽象中介者(Mediator):定义一个接口,该接口用于定义各同事(Colleague)对象之间进行通信需要的方法。
  2. 具体中介者(ConcreteMediator):实现抽象中介者接口,通过协调各个同事对象来实现协作行为,了解并维护它的各个同事,它维持了对各个同事对象的引用。
  3. 抽象同事类(Colleague):定义各个同事类公有的方法,并声明了一些抽象方法来供子类实现,同时它维持了一个对抽象中介者类的引用,其子类可以通过该引用来与中介者通信。
  4. 具体同事类(ConcreteColleague):实现抽象同事类,每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信。

三、中介者模式的理解

  1. 降低耦合度:通过引入中介者对象,各个对象之间的直接依赖关系被减少,使得系统结构更加灵活和可扩展。
  2. 简化交互:中介者模式将对象之间的多对多交互关系转换为中介者与各个对象之间的一对多关系,简化了对象之间的交互逻辑。
  3. 易于维护和扩展:由于对象之间的交互被集中到中介者对象中,因此当需要修改或扩展对象之间的交互时,只需修改中介者对象,而不需要修改各个对象的代码。

        然而,中介者模式也有其局限性。如果系统中存在大量的同事类,中介者可能会变得非常复杂,难以维护。因此,在实际应用中需要权衡利弊,根据具体情况决定是否采用该模式。

四、中介者模式的实践

        下面我们通过具体的Java代码示例来展示中介者模式的实践应用。

示例一:简单的聊天系统

        假设我们要设计一个可以让多人参与进去的聊天室,该聊天室需要实现发送消息和新增用户的功能。

        首先,我们定义聊天室的接口ChatRoom,其中包含两个方法sendMessageaddUser,分别代表发送消息和新增用户。这里的ChatRoom就是抽象的中介者类。

public interface ChatRoom {void sendMessage(String msg, String userId);void addUser(User user);
}


        然后,我们创建一个ChatRoom的实现类ChatRoomImpl,使用addUser来添加需要聊天的用户对象,同时这里再使用一个Map来保存添加时需要用来进行通信的对象列表。在发送消息sendMessage的方法中,我们通过userId指定某个对象来接收消息。

import java.util.HashMap;
import java.util.Map;public class ChatRoomImpl implements ChatRoom {private Map<String, User> usersMap = new HashMap<>();@Overridepublic void sendMessage(String msg, String userId) {User u = usersMap.get(userId);u.receive(msg);}@Overridepublic void addUser(User user) {this.usersMap.put(user.getId(), user);}
}


        接下来,我们定义一个抽象组件类User,它持有一个ChatRoom的引用,并声明了发送消息send和接收消息receive的抽象方法。

public abstract class User {private ChatRoom mediator;private String id;private String name;public User(ChatRoom room, String id, String name) {this.mediator = room;this.name = name;this.id = id;}public abstract void send(String msg, String userId);public abstract void receive(String msg);public ChatRoom getMediator() {return mediator;}public String getId() {return id;}public String getName() {return name;}
}


        然后,我们实现一个具体的组件类ChatUser,并实现发送消息send和接收消息receive的方法。

public class ChatUser extends User {public ChatUser(ChatRoom room, String id, String name) {super(room, id, name);}@Overridepublic void send(String msg, String userId) {getMediator().sendMessage(msg, userId);}@Overridepublic void receive(String msg) {System.out.println(getName() + "收到消息: " + msg);}
}


        最后,我们在客户端代码中创建中介者和同事对象的实例,并将它们关联起来。

public class ChatDemo {public static void main(String[] args) {ChatRoom chatRoom = new ChatRoomImpl();User user1 = new ChatUser(chatRoom, "1", "张三");User user2 = new ChatUser(chatRoom, "2", "李四");chatRoom.addUser(user1);chatRoom.addUser(user2);user1.send("你好, 李四", "2");user2.send("你好, 张三", "1");}
}


        运行上述代码,输出结果如下:

李四收到消息: 你好, 李四
张三收到消息: 你好, 张三


        通过这个示例,我们可以看到,聊天系统中的用户对象(User)通过中介者(ChatRoom)来进行间接通信,而不需要直接引用对方。这样,不仅降低了用户对象之间的耦合度,还简化了用户之间的交互逻辑。

示例二:多架飞机降落

        假设有多架飞机需要跑道降落,塔台作为中介者指挥飞机降落。每一架飞机都是一个组件,拥有一些相同的行为,塔台作为中介者负责指挥飞机的降落。

        首先,我们定义抽象中介者接口TowerMediator,它包含通知方法notify、注册方法register和移除方法remove

public interface TowerMediator {void notify(String type, String track);void register(AirplaneComponent colleague);void remove(AirplaneComponent colleague);
}


        然后,我们实现具体的中介者类AirlinerConcreteMediator,它持有一个List来管理组件对象(即飞机)。

import java.util.ArrayList;
import java.util.List;public class AirlinerConcreteMediator implements TowerMediator {private List<AirplaneComponent> colleagues = new ArrayList<>();@Overridepublic void notify(String type, String track) {for (AirplaneComponent airplaneComponent : colleagues) {if (!type.equalsIgnoreCase(airplaneComponent.getAirplaneType())) {continue;}airplaneComponent.landing(track);}}@Overridepublic void register(AirplaneComponent colleague) {colleagues.add(colleague);}@Overridepublic void remove(AirplaneComponent colleague) {colleagues.remove(colleague);}
}


        接下来,我们定义抽象组件类AirplaneComponent,它持有一个中介者对象的引用,并声明了一个抽象方法landing

public abstract class AirplaneComponent {public String airplaneType;private TowerMediator towerMediator;public AirplaneComponent(String airplaneType, TowerMediator towerMediator) {this.airplaneType = airplaneType;this.towerMediator = towerMediator;}public abstract void landing(String track);public TowerMediator getTowerMediator() {return towerMediator;}
}


        然后,我们实现具体的组件类AirlinerConcreteComponent,它代表客机。

public class AirlinerConcreteComponent extends AirplaneComponent {public AirlinerConcreteComponent(String airplaneType, TowerMediator towerMediator) {super(airplaneType, towerMediator);}@Overridepublic void landing(String track) {System.out.println(airplaneType + "正在跑道" + track + "上降落");}
}


        最后,我们在客户端代码中创建中介者和组件对象的实例,并将它们关联起来。

// 客户端代码
public class AirportDemo {public static void main(String[] args) {// 创建中介者(塔台)TowerMediator towerMediator = new AirlinerConcreteMediator();// 创建具体的组件(飞机),并注册到中介者AirplaneComponent airplane1 = new AirlinerConcreteComponent("波音737", towerMediator);AirplaneComponent airplane2 = new AirlinerConcreteComponent("空客A320", towerMediator);AirplaneComponent airplane3 = new AirlinerConcreteComponent("波音787", towerMediator);// 通知中介者进行降落安排(这里假设有两个跑道:Runway 1 和 Runway 2)towerMediator.notify("波音737", "Runway 1");towerMediator.notify("空客A320", "Runway 2");towerMediator.notify("波音787", "Runway 1"); // 假设波音787可以等待或使用另一个空闲跑道// 注意:由于中介者内部已经维护了组件的列表,因此不需要显式地移除组件,// 除非在程序的某个阶段需要动态地卸载组件。}
}

        在这个示例中,AirportDemo类的main方法是客户端代码,它创建了中介者AirlinerConcreteMediator的实例,并创建了多个具体的组件(飞机)实例,这些实例都被注册到了中介者中。然后,通过调用中介者的notify方法,模拟了飞机请求降落的过程,并分配了跑道。

        运行AirportDemo类的main方法,您将看到类似以下的输出:

波音737 正在跑道 Runway 1 上降落
空客A320 正在跑道 Runway 2 上降落
波音787 正在跑道 Runway 1 上降落

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

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

相关文章

PlantUML——类图

背景 类图是UML模型中的静态视图&#xff0c;其主要作用包括&#xff1a; 描述系统的结构化设计&#xff0c;显示出类、接口以及它们之间的静态结构和关系。简化对系统的理解&#xff0c;是系统分析与设计阶段的重要产物&#xff0c;也是系统编码和测试的重要模型依据。 在U…

【Java知识】Java进阶-如何开启远程调式

java远程调试 概述Java远程调试的开启与底层原理开启Java远程调试底层原理 JVM参数 概述 Java远程调试的开启与底层原理 开启Java远程调试 Java远程调试允许开发者在本地IDE&#xff08;如Eclipse、IntelliJ IDEA等&#xff09;中调试运行在远程服务器上的Java应用程序。以下…

入选国家数据局案例!浙江“一体化智能化公共数据平台”总体架构详解~

国家数据局在2024中国国际大数据产业博览会上发布了首批50个数字中国建设典型案例。案例涉及数据基础设施、数据资源、数字技术创新、数字政府、数字经济、数字社会、数字文化、数字生态文明等领域&#xff0c;集中反映了近年来数字中国建设的实践和成效。 其中&#xff0c;由…

vscode IntelliSense Configurations

IntelliSense 是一个强大的代码补全和代码分析功能&#xff0c;它可以帮助开发者提高编程效率。图中显示的是 VSCode 的 IntelliSense 配置界面&#xff0c;具体配置如下&#xff1a; Compiler path&#xff08;编译器路径&#xff09;: 这里指定了用于构建项目的编译器的完整路…

同三维TL200H2S6 6机位精品教育录播主机

录制点播、直播导播、互动、音频处理器、中控等多功能为一体 8路视频输入:6路SDI1路HDMI1(4K30)1路(3选1:HDMI2/2路VGA) 2路视频输出&#xff1a;1路HDMI1(4K30)1路&#…

欢乐斗地主案例

1&#xff0c;创建对象 package anlidoudizhu;public class pai implements Comparable<pai> {private Double value;private String name;Overridepublic int compareTo(pai o) {return -Double.compare(this.value,o.value);}//升序排序&#xff0c;treeset集合public…

技术型企业如何高效搭建企业博客以增强品牌影响力和市场竞争力

在数字化时代&#xff0c;技术型企业面临着激烈的市场竞争和快速变化的行业环境。为了在这场竞争中脱颖而出&#xff0c;企业需要寻找新的营销渠道和品牌建设工具。企业博客作为一种低成本、高效率的在线内容平台&#xff0c;已经成为技术型企业增强品牌影响力和市场竞争力的重…

go-zero(十二)消息队列

go zero 消息队列 在微服务架构中&#xff0c;消息队列主要通过异步通信实现服务间的解耦&#xff0c;使得各个服务可以独立发展和扩展。 go-zero中使用的队列组件go-queue&#xff0c;是gozero官方实现的基于Kafka和Beanstalkd 的消息队列框架,我们使用kafka作为演示。 一、…

【JAVA高级篇教学】第二篇:使用 Redisson 实现高效限流机制

在高并发系统中&#xff0c;限流是一项非常重要的技术手段&#xff0c;用于保护后端服务&#xff0c;防止因流量过大导致系统崩溃。本文将详细介绍如何使用 Redisson 提供的 RRateLimiter 实现分布式限流&#xff0c;以及其原理、使用场景和完整代码示例。 目录 一、什么是限流…

基于卷积神经网络的Caser算法

将一段交互序列嵌入到一个以时间为纵轴的平面空间中形成“一张图”后&#xff0c;基于卷积序列嵌入的推荐&#xff08;Caser&#xff09;算法利用多个不同大小的卷积滤波器&#xff0c;来捕捉序列中物品间的点级&#xff08;point-level&#xff09;、联合的&#xff08;union-…

ubuntu下的chattts 学习5:Example: self introduction

代码 import ChatTTS import torch import torchaudiochat ChatTTS.Chat() chat.load(compileFalse) # Set to True for better performance ################################### inputs_en """ chat T T S is a text to speech model designed for dialogu…

【银河麒麟高级服务器操作系统】修改容器中journal服务日志存储位置无效—分析及解决方案

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 服务器环境以及配置 【机型】 整机类型/架构&am…

HTML:表格重点

用表格就用table caption为该表上部信息&#xff0c;用来说明表的作用 thead为表头主要信息&#xff0c;效果加粗 tbody为表格中的主体内容 tr是 table row 表格的行 td是table data th是table heading表格标题 &#xff0c;一般表格第一行的数据都是table heading

[创业之路-187]:《华为战略管理法-DSTE实战体系》-1-从UTStarcom的发展历程,如何辩证的看企业初期发展太顺利中的危机

目录 一、UTStarcom&#xff08;UT斯达康&#xff09;的发展历程 1、创立与初期发展 2、快速成长与上市 3、技术创新与业务拓展 4、战略调整与持续发展 二、从UTStarcom的发展历程&#xff0c;如何辩证的看企业初期发展太顺利中的危机 1、企业初期发展的顺利表现 2、顺…

ubuntu系统生成SSL证书配置https

自签名【Lets Encrypt】的测试证书&#xff0c;有效期三个月。 第一步&#xff1a;安装acme&#xff0c;如果没有安装git&#xff0c;需要提前安装 下载came资源 git clone https://github.com/Neilpang/acme.sh.git 无法访问&#xff0c;可以试用gitee的资源&#xff0c;安…

CentOS 7 环境下常见的操作和配置

目录 1. CentOS 7 中的 vsftpd 配置与使用 安装与启动 vsftpd 配置 vsftpd&#xff08;/etc/vsftpd/vsftpd.conf&#xff09; 常见命令 2. 使用 yum 包管理器 3. 安全性与防火墙配置 开放端口 4. 使用 systemd 管理服务 5. SELinux 配置 查看 SELinux 状态 临时禁用…

《AI教学能力:开启教育新纪元》

一、摘要 AI 在教育领域的应用日益广泛&#xff0c;对教学能力产生了深远影响。本文将深入探讨 AI 教学能力的核心技术、实际应用、教学模式与策略、全球实践以及未来趋势&#xff0c;为教育的现代化发展提供参考。 摘要&#xff1a; AI 在教育领域的应用及其对教学能力的影响…

【信息系统项目管理师】第10章:项目进度管理过程详解

文章目录 一、规划进度管理1、输入2、工具与技术3、输出 二、定义活动1、输入2、工具与技术3、输出 三、排列活动顺序1、输入2、工具与技术3、输出 四、估算活动持续时间1、输入2、工具与技术3、输出 五、制订进度计划1、输入2、工具与技术3、输出 六、控制进度1、输入2、工具与…

域渗透入门靶机之HTB-Cicada

easy难度的windows靶机 信息收集 端口探测 nmap -sT --min-rate 10000 -p- 10.10.11.35 -oA ./port 发现开放了53&#xff0c;88&#xff0c;389等端口&#xff0c;推测为域控 进一步信息收集&#xff0c;对爆破的端口进行更加详细的扫描 小tips&#xff1a;对于众多的端口&…

pgsql中如何设计维度表、度量表、事实表、大宽表

在 PostgreSQL 中设计维度表、度量表、事实表和大宽表需要遵循数据仓库建模的最佳实践。以下是如何设计这些表的详细步骤&#xff0c;包括建模的结构、示例 SQL 代码以及注意事项。 1. 维度表 (Dimension Table) 设计步骤&#xff1a; 确定维度&#xff1a;识别需要的维度&am…