当前位置: 首页 > news >正文

Java设计模式:中介者模式详解与最佳实践

Java设计模式:中介者模式详解与最佳实践

1. 引言

在软件开发过程中,特别是复杂系统的构建中,模块间的交互往往成为影响代码质量的重要因素。当模块之间耦合度过高时,系统的维护、扩展和理解成本都会显著增加。为了降低模块之间的耦合度,保持系统的灵活性和可维护性,我们可以使用设计模式中的中介者模式(Mediator Pattern)。本篇文章将详细介绍中介者模式的概念、优点及其在Java中的应用,并通过实例代码演示如何实现这一模式。

2. 中介者模式概述
2.1 中介者模式定义

中介者模式是一种行为型设计模式,用于减少多个对象之间的耦合。它通过引入一个中介者对象,使得各个对象不直接相互引用,而是通过中介者对象进行通信。这种模式将对象之间的复杂关系转换为简化的星型关系,从而降低对象之间的耦合度。

2.2 中介者模式的适用场景

中介者模式主要适用于以下场景:

  1. 对象之间存在复杂的交互关系:如果对象之间的关系错综复杂,直接交互会导致代码难以维护,此时适合引入中介者模式。
  2. 需要复用对象,但又希望能在不同的上下文中灵活互通:通过中介者模式,可以在不同的中介者中定义不同的交互逻辑。
  3. 希望将交互行为封装到一个独立的对象中:这样可以更好地控制、管理和扩展交互逻辑,而不影响对象本身的设计。
2.3 中介者模式的优缺点

优点

  1. 降低对象之间的耦合:通过中介者对象,各模块不再直接引用彼此,减少了代码的耦合度。
  2. 集中控制交互逻辑:所有的交互都在中介者中处理,可以统一管理和修改,逻辑集中且清晰。
  3. 提高代码的可维护性和可扩展性:当新增或修改交互逻辑时,只需更改中介者,减少对原有代码的影响。

缺点

  1. 可能导致中介者过于复杂:如果交互逻辑过多,可能导致中介者类变得庞大和复杂,难以维护。
  2. 降低了对象的独立性:对象过度依赖中介者,可能会使得对象在没有中介者的情况下难以使用。
3. 中介者模式的结构与实现
3.1 中介者模式的结构

中介者模式主要由以下几个角色组成:

  1. Mediator(中介者):定义了同事对象之间交互的接口。
  2. ConcreteMediator(具体中介者):实现了中介者接口,协调各个同事对象之间的交互。
  3. Colleague(同事类):每个同事类只知道自己的行为,不了解其他同事类的情况,它们通过中介者与其他同事类进行通信。
3.2 UML类图

在详细介绍代码实现之前,我们先看一下中介者模式的UML类图:

       +------------------+|     Mediator     |<-------------------++------------------+                    ||  + notify()      |                    |+------------------+                    |^                              ||                              |+------------------+                      || ConcreteMediator |                      |+------------------+                      ||  + notify()      |                      |+------------------+                      |^                              ||                              |+------------------+        +------------------+|     ColleagueA   |        |    ColleagueB    |+------------------+        +------------------+|  + send()        |        |  + send()        ||  + receive()     |        |  + receive()     |+------------------+        +------------------+
3.3 代码实现

以下是中介者模式的Java代码实现,展示了一个简单的聊天系统,多个用户(同事类)通过中介者进行消息传递。

// 定义中介者接口
interface Mediator {void sendMessage(String message, Colleague colleague);void addColleague(Colleague colleague);
}// 具体中介者类
class ConcreteMediator implements Mediator {private List<Colleague> colleagues;public ConcreteMediator() {this.colleagues = new ArrayList<>();}@Overridepublic void sendMessage(String message, Colleague colleague) {for (Colleague c : colleagues) {// 不发送消息给发送者本身if (c != colleague) {c.receive(message);}}}@Overridepublic void addColleague(Colleague colleague) {colleagues.add(colleague);}
}// 定义同事类的抽象
abstract class Colleague {protected Mediator mediator;public Colleague(Mediator mediator) {this.mediator = mediator;}public abstract void send(String message);public abstract void receive(String message);
}// 具体的同事类:UserA
class UserA extends Colleague {public UserA(Mediator mediator) {super(mediator);}@Overridepublic void send(String message) {System.out.println("UserA发送消息: " + message);mediator.sendMessage(message, this);}@Overridepublic void receive(String message) {System.out.println("UserA收到消息: " + message);}
}// 具体的同事类:UserB
class UserB extends Colleague {public UserB(Mediator mediator) {super(mediator);}@Overridepublic void send(String message) {System.out.println("UserB发送消息: " + message);mediator.sendMessage(message, this);}@Overridepublic void receive(String message) {System.out.println("UserB收到消息: " + message);}
}// 客户端代码
public class MediatorPatternDemo {public static void main(String[] args) {ConcreteMediator mediator = new ConcreteMediator();Colleague userA = new UserA(mediator);Colleague userB = new UserB(mediator);mediator.addColleague(userA);mediator.addColleague(userB);userA.send("你好,UserB!");userB.send("你好,UserA!我收到了你的消息。");}
}

在这个示例中,ConcreteMediator类作为中介者,负责管理Colleague对象之间的消息传递。每个Colleague对象(如UserAUserB)通过中介者发送和接收消息,而不需要直接引用彼此。

3.4 代码分析
  1. 松散耦合UserAUserB并不知道对方的存在,它们只通过ConcreteMediator进行通信。这样,如果我们增加一个新的同事类,例如UserC,并不需要修改UserAUserB的代码,只需要在中介者中处理其交互即可。

  2. 单一职责原则:每个同事类只负责发送和接收消息,不关心如何传递消息。中介者类集中管理消息的路由逻辑,使得同事类的职责单一化。

  3. 扩展性:通过中介者模式,可以轻松地增加新的同事类或修改交互逻辑,而不会影响现有的类。

4. 中介者模式的最佳实践
4.1 在大型系统中的应用

在大型系统中,模块之间的交互关系往往非常复杂,使用中介者模式可以有效降低模块间的耦合度。例如,在企业级应用中,用户界面的各个组件之间通常需要频繁交互,使用中介者模式可以使界面组件之间的通信更加清晰和灵活。

4.2 在消息传递系统中的应用

中介者模式非常适合用于消息传递系统中。例如,在即时通讯应用中,各个客户端可以通过服务器(中介者)进行消息传递。服务器负责管理客户端的连接和消息的转发,而客户端只需要关注如何发送和接收消息。

4.3 在微服务架构中的应用

在微服务架构中,各个服务之间的通信往往通过消息队列或事件总线来实现。这种通信方式本质上就是中介者模式的一种应用。通过引入一个消息中介者,可以解耦微服务之间的依赖关系,增强系统的扩展性和容错性。

5. 中介者模式的变体与改进
5.1 事件驱动的中介者模式

在某些情况下,可以结合事件驱动的方式来实现中介者模式。这种变体通常在GUI应用程序或实时系统中

使用,通过事件机制来触发中介者的动作,而不是直接调用方法。

interface EventMediator {void notify(String event, Colleague colleague);
}class EventDrivenMediator implements EventMediator {private Map<String, List<Colleague>> listeners = new HashMap<>();public void subscribe(String event, Colleague colleague) {listeners.putIfAbsent(event, new ArrayList<>());listeners.get(event).add(colleague);}@Overridepublic void notify(String event, Colleague colleague) {if (listeners.containsKey(event)) {for (Colleague c : listeners.get(event)) {if (c != colleague) {c.receive(event + " triggered by " + colleague.getClass().getSimpleName());}}}}
}class EventUserA extends Colleague {public EventUserA(EventMediator mediator) {super(mediator);}public void triggerEvent(String event) {System.out.println("EventUserA triggers event: " + event);mediator.notify(event, this);}@Overridepublic void send(String message) {// Implementation not required for this example}@Overridepublic void receive(String message) {System.out.println("EventUserA received: " + message);}
}class EventUserB extends Colleague {public EventUserB(EventMediator mediator) {super(mediator);}@Overridepublic void send(String message) {// Implementation not required for this example}@Overridepublic void receive(String message) {System.out.println("EventUserB received: " + message);}
}public class EventDrivenMediatorDemo {public static void main(String[] args) {EventDrivenMediator mediator = new EventDrivenMediator();EventUserA userA = new EventUserA(mediator);EventUserB userB = new EventUserB(mediator);mediator.subscribe("event1", userB);userA.triggerEvent("event1");}
}

在这个例子中,中介者模式结合了事件驱动的思想,EventUserA触发了event1事件,EventUserB通过中介者接收到该事件。事件驱动的中介者模式提高了系统的响应性和灵活性。

5.2 中介者模式与观察者模式的结合

中介者模式可以与观察者模式结合使用,通过将观察者模式中的订阅者通知功能整合到中介者中,从而实现更复杂的交互逻辑。这种结合方式特别适用于需要动态管理和通知多个组件的场景。

6. 结论

中介者模式通过引入一个中介者对象,减少了系统中对象之间的直接耦合,从而提高了代码的可维护性和扩展性。在复杂系统的构建中,中介者模式尤其适合处理对象之间复杂的交互关系,避免了代码的混乱和难以维护。

通过本文的详细讲解与代码示例,我们深入理解了中介者模式的核心思想、适用场景以及实际应用中的最佳实践。在实际开发中,掌握并合理运用中介者模式,可以有效提升系统设计的质量,降低维护成本。

相关文章:

Java设计模式:中介者模式详解与最佳实践

Java设计模式&#xff1a;中介者模式详解与最佳实践 1. 引言 在软件开发过程中&#xff0c;特别是复杂系统的构建中&#xff0c;模块间的交互往往成为影响代码质量的重要因素。当模块之间耦合度过高时&#xff0c;系统的维护、扩展和理解成本都会显著增加。为了降低模块之间的…...

Matlab绘制像素风字母颜色及透明度随机变化动画

本文是使用 Matlab 绘制像素风字母颜色及透明度随机变化动画的教程 实现效果 实现代码 如果需要更改为其他字母组合&#xff0c;在下面代码的基础上简单修改就可以使用。 步骤&#xff1a;(1) 定义字母形状&#xff1b;(2) 给出字母组合顺序&#xff1b;(3) 重新运行程序&#…...

C:每日一题:二分查找

1、知识介绍&#xff1a; 1.1 概念&#xff1a; 二分查找是一种在有序数组中查找某一特定元素的搜索算法 1.2 基本思想&#xff1a; 每次将待查找的范围缩小一半&#xff0c;通过比较中间元素与目标元素的大小&#xff0c;来决定是在左半部分还是右半部分继续查找。 举个生…...

python Django中使用ORM进行分组统计并降序排列

python Django中使用ORM进行分组统计并降序排列 # 使用supplier和Count进行分组统计,其中supplier为MyModel的一个字段 supplier_counts MyModel.objects.values(supplier).annotate(countCount(supplier)).order_by(-count) # 输出统计结果 for supplier_count in supplier_…...

QT C++ 编写modbus 总结

[开源库的使用]libModbus编译及使用_libmodbus库-CSDN博客 libmodbus的下载与编译_modbus库文件下载-CSDN博客 【QT5】解决 QT 界面中文显示乱码问题_qt5输出中文乱码解决方法-CSDN博客 Qt&#xff1a;解决qt修改完ui文件起不到作用_qt ui文件修改后不生效-CSDN博客...

基于SpringBoot的网络海鲜市场系统的设计与实现

TOC springboot219基于SpringBoot的网络海鲜市场系统的设计与实现 绪论 1.1 选题背景 当人们发现随着生产规模的不断扩大&#xff0c;人为计算方面才是一个巨大的短板&#xff0c;所以发明了各种计算设备&#xff0c;从结绳记事&#xff0c;到算筹&#xff0c;以及算盘&…...

c#相关基础知识

c#参数4种种别 值参&#xff1a;像Java的正常数据的传输 ref&#xff1a;对参数的指向是参数本身的地址&#xff0c;而不是数据的副本&#xff0c;所以可以对数据进行直接操作 out: 绑定控件&#xff0c;控件传输值赋值给类中的内部类 待定...

注意力机制 — 它是什么以及它是如何工作的

一、说明 注意力机制是深度学习领域的一个突破。它们帮助模型专注于数据的重要部分&#xff0c;并提高语言处理和计算机视觉等任务的理解和性能。这篇文章将深入探讨深度学习中注意力的基础知识&#xff0c;并展示其背后的主要思想。 二、注意力机制回顾 在我们谈论注意力之前&…...

学习嵌入式第二十六天

进程线程 1.进程的概念 2.进程 和 程序 硬盘中程序 &#xff0c;加载到内存中&#xff0c;运行起来&#xff0c;就是进程 创建线程 pthread_create posix thread create 线程执行 ---体现在线程执行函数 (回调函数) 线程退出 ---pthread_exit() …...

speech语音audio音频

在信号处理和语言技术领域&#xff0c;speech 和 audio 是两个相关但不同的概念。它们有各自的定义和应用场景。以下是对这两个术语的详细解释&#xff1a; 1. Speech&#xff08;语音&#xff09; Speech 主要指的是人类说话时产生的声音。它是人类语言交流的一种主要形式&a…...

最常用的正则表达式规则和语法

正则表达式(Regular Expression,简称 regex)是一种用于匹配字符串的强大工具。它使用特定的语法规则来定义字符串模式,可以用来搜索、替换、验证字符串等。以下是一些常用的正则表达式规则和语法: 1. 基本字符匹配 . :匹配任意单个字符(除了换行符)。 示例:a.c 可以匹…...

Datawhale X 魔搭 AI夏令营第四期-魔搭生图task1学习笔记

根据教程提供的链接&#xff0c;进入相应文章了解魔搭生图的主要工作是通过对大量图片的训练&#xff0c;生成自己的模型&#xff0c;然后使用不同的正向、反向提示词使模型输出对应的图片 1.官方跑baseline教程链接:Task 1 从零入门AI生图原理&实践 2.简单列举一下赛事的…...

WPF中XAML相对路径表示方法

在WPF XAML中&#xff0c;相对路径是一种非常实用的方式来引用资源文件&#xff0c;如图像、样式表和其他XAML文件。相对路径可以帮助您构建更加灵活和可移植的应用程序&#xff0c;因为它允许资源文件的位置相对于XAML文件的位置进行定位。 相对路径的表示方法 在XAML中&…...

操作系统内存管理技术详解

操作系统内存管理技术详解&#xff1a;第一部分 引言 操作系统作为计算机系统的核心组件&#xff0c;负责管理硬件资源、提供用户接口和运行应用程序。在操作系统的众多功能中&#xff0c;内存管理无疑是最为关键的技术之一。本文将深入探讨操作系统内存管理的背后技术&…...

python之numpy(2 创建矩阵)

numpy创建矩阵 前面提到&#xff0c;numpy主要是针对数组和矩阵的操作。下面我们分别创建数组和矩阵。 import numpy as np x0np.array([1,2,3,4]) x1np.array([[1,2,3,4],[1,2,3,4]]) print(x0,x1,sep\n) 在numpy中&#xff0c;使用array创建数组和矩阵。其中&#xff0c;创…...

git stage 和 git unstage

无意间遇到 git stage 和 git unstage&#xff0c;感觉有点陌生&#xff0c;简单了解一下这两个概念。 在 Git 中&#xff0c;stage 和 unstage 是与暂存区操作相关的术语&#xff0c;它们用于管理文件的状态&#xff0c;决定哪些更改会在下次的提交中。 1. git stage git s…...

C#使用反射和特性的优缺点

使用反射&#xff08;Reflection&#xff09;和特性&#xff08;Attributes&#xff09;在C#中有其特定的应用场景&#xff0c;同时也带来了一些优缺点&#xff1a; 反射的优点&#xff1a; 动态性&#xff1a;反射允许程序在运行时查询和操作对象的类型信息&#xff0c;提供…...

C语言:字符串函数strcat

该函数用于字符串拼接。 使用方法如下&#xff1a; #include<stdio.h> #include<string.h>int main() {char str[20] "abcd";char str1[] "1234";//strcat(str,str1);//不安全&#xff0c;所以用strcat_sstrcat_s(str, 20, str1);printf(&…...

haproxy总结与实验

一、负载均衡 1.1 简述负载均衡 在高并发的业务场景下&#xff0c;解决单个节点压力过大&#xff0c;导致Web服务响应过慢&#xff0c;特别是严重的情况下导致服务瘫痪&#xff0c;无法正常提供服务的问题&#xff0c;而负载均衡的目的就是为了维护系统稳定可靠。负载均衡&…...

VS实用调试技巧(程序员的必备技能)

调试的重要性 在我们写代码的时候&#xff0c;如果程序出现了bug&#xff0c;那么下一步就是找到bug并修复bug!而这个找问题的过程就被称为调试&#xff08;英文叫debug&#xff0c;消灭bug的意思&#xff09;。 调试能观察到程序内部执行的细节&#xff0c;可以增加程序员对…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...