中介者模式在Java中的实现:设计模式精解
中介者模式在Java中的实现:设计模式精解
中介者模式(Mediator Pattern)是一种行为型设计模式,用于定义一个中介者对象,以封装一系列对象之间的交互,从而使对象之间的交互不再直接发生,减少了系统中的耦合度。中介者模式适用于对象之间的交互复杂的场景,使得各个对象之间的协作变得更加简单和清晰。
本文将详细解析中介者模式在Java中的实现,介绍其结构、优缺点,并通过具体的代码示例展示如何在Java中使用中介者模式。
1. 中介者模式的基本概念
中介者模式的核心思想是将多个对象之间的复杂交互集中到一个中介者对象中,从而使得对象之间不再直接通信,降低系统的耦合度。这样,当系统中需要增加或修改对象时,只需要修改中介者对象的逻辑,而不需要修改其他对象。
1.1 中介者模式的主要角色
- Mediator(中介者接口):定义了与各个Colleague(同事)对象之间交互的接口。
- ConcreteMediator(具体中介者):实现Mediator接口,负责协调各个Colleague对象之间的通信和协作。
- Colleague(同事接口):定义了中介者和各个具体同事对象的接口。
- ConcreteColleague(具体同事):实现Colleague接口,与ConcreteMediator进行交互。
1.2 中介者模式的UML类图
+------------------+
| Mediator |
+------------------+
| +mediate() |
+------------------+^||
+------------------+ +------------------+
| ConcreteMediator | | ConcreteMediator |
+------------------+ +------------------+
| -colleague1 | | -colleague2 |
| -colleague2 | | -colleague2 |
| +mediate() | | +mediate() |
+------------------+ +------------------+^ ^| || |
+------------------+ +------------------+
| ConcreteColleague| | ConcreteColleague|
| 1 | | 2 |
+------------------+ +------------------+
| -mediator | | -mediator |
| +operation() | | +operation() |
+------------------+ +------------------+
2. 中介者模式的实现
2.1 示例:聊天室
假设我们正在实现一个聊天室,其中多个用户通过一个聊天室中介者进行消息的发送和接收。每个用户对象都可以发送和接收消息,但它们之间的直接通信将通过中介者对象来完成。
2.1.1 中介者接口
// Mediator Interface
public interface ChatRoomMediator {void sendMessage(String message, User user);void addUser(User user);
}
2.1.2 具体中介者
// ConcreteMediator
import java.util.ArrayList;
import java.util.List;public class ChatRoom implements ChatRoomMediator {private List<User> users;public ChatRoom() {this.users = new ArrayList<>();}@Overridepublic void sendMessage(String message, User user) {for (User u : users) {// Message should not be sent to the user who sent itif (u != user) {u.receiveMessage(message);}}}@Overridepublic void addUser(User user) {this.users.add(user);}
}
2.1.3 同事接口
// Colleague Interface
public abstract class User {protected ChatRoomMediator mediator;protected String name;public User(ChatRoomMediator mediator, String name) {this.mediator = mediator;this.name = name;}public abstract void sendMessage(String message);public abstract void receiveMessage(String message);
}
2.1.4 具体同事
// ConcreteColleague1
public class ConcreteUser extends User {public ConcreteUser(ChatRoomMediator mediator, String name) {super(mediator, name);}@Overridepublic void sendMessage(String message) {System.out.println(this.name + " sends: " + message);mediator.sendMessage(message, this);}@Overridepublic void receiveMessage(String message) {System.out.println(this.name + " receives: " + message);}
}
2.1.5 主类
// Main class to demonstrate
public class Main {public static void main(String[] args) {ChatRoomMediator mediator = new ChatRoom();User user1 = new ConcreteUser(mediator, "Alice");User user2 = new ConcreteUser(mediator, "Bob");User user3 = new ConcreteUser(mediator, "Charlie");mediator.addUser(user1);mediator.addUser(user2);mediator.addUser(user3);user1.sendMessage("Hello, everyone!");user2.sendMessage("Hi Alice!");}
}
2.2 示例:订单处理系统
假设我们正在实现一个订单处理系统,其中订单的处理涉及到多个步骤,如验证、支付、发货等。每个步骤都通过一个处理器对象进行处理,而这些处理器对象通过一个中介者对象来协调工作。
2.2.1 中介者接口
// Mediator Interface
public interface OrderMediator {void processOrder();void setOrder(Order order);void setPayment(Payment payment);void setShipping(Shipping shipping);
}
2.2.2 具体中介者
// ConcreteMediator
public class OrderProcessingMediator implements OrderMediator {private Order order;private Payment payment;private Shipping shipping;@Overridepublic void processOrder() {if (order != null && payment != null && shipping != null) {order.process();payment.process();shipping.process();} else {System.out.println("Order, payment or shipping is missing.");}}@Overridepublic void setOrder(Order order) {this.order = order;}@Overridepublic void setPayment(Payment payment) {this.payment = payment;}@Overridepublic void setShipping(Shipping shipping) {this.shipping = shipping;}
}
2.2.3 同事接口
// Colleague Interface
public interface OrderProcessComponent {void process();
}
2.2.4 具体同事
// ConcreteColleague1
public class Order implements OrderProcessComponent {@Overridepublic void process() {System.out.println("Processing order.");}
}// ConcreteColleague2
public class Payment implements OrderProcessComponent {@Overridepublic void process() {System.out.println("Processing payment.");}
}// ConcreteColleague3
public class Shipping implements OrderProcessComponent {@Overridepublic void process() {System.out.println("Processing shipping.");}
}
2.2.5 主类
// Main class to demonstrate
public class Main {public static void main(String[] args) {OrderProcessingMediator mediator = new OrderProcessingMediator();Order order = new Order();Payment payment = new Payment();Shipping shipping = new Shipping();mediator.setOrder(order);mediator.setPayment(payment);mediator.setShipping(shipping);mediator.processOrder();}
}
3. 中介者模式的优缺点
3.1 优点
- 降低耦合度:通过将对象间的交互集中到中介者对象中,各个对象之间不再直接通信,从而降低了系统的耦合度。
- 集中控制:所有对象间的交互逻辑集中在中介者中,便于管理和修改。
- 提高灵活性:可以在不修改同事对象的情况下,修改中介者的交互逻辑,增加新的功能或修复问题。
3.2 缺点
- 中介者复杂化:中介者对象可能变得过于复杂,尤其是在处理复杂的对象交互时。
- 单点故障:中介者可能成为系统中的瓶颈或单点故障点,一旦中介者出现问题,所有对象的交互都会受到影响。
4. 实践建议
- 使用场景:中介者模式适用于需要处理复杂交互的场景,尤其是当对象之间的交互逻辑比较复杂时。
- 注意复杂度:在使用中介者模式时,需要注意中介者的复杂度,尽量避免中介者变得过于庞大,可以考虑将其拆分为多个中介者。
- 结合其他模式:中介者模式可以与其他设计模式结合使用,例如与观察者模式结合,用于处理复杂的事件通知机制。
5. 总结
中介者模式是一种有效
的行为型设计模式,通过将对象之间的交互集中到中介者对象中,降低了系统的耦合度,提高了系统的灵活性和可维护性。通过具体的Java代码示例,本文展示了中介者模式在实际开发中的应用,并介绍了中介者模式的优缺点和实践建议。希望这些内容能帮助你更好地理解和应用中介者模式,在实际开发中提升系统的设计质量。
相关文章:
中介者模式在Java中的实现:设计模式精解
中介者模式在Java中的实现:设计模式精解 中介者模式(Mediator Pattern)是一种行为型设计模式,用于定义一个中介者对象,以封装一系列对象之间的交互,从而使对象之间的交互不再直接发生,减少了系…...

PyQt编程快速上手
Python GUI安装 GUI就是图形用户界面的意思,在Python中使用PyQt可以快速搭建自己的应用,使得自己的程序看上去更加高大上,学会GUI编程可以使得自己的软件有可视化的结果。 如果你想用Python快速制作界面,可以安装PyQt:…...
Docker Swarm管理
Docker Swarm管理 前置知识点 Docker Swarm 是 Docker 公司 2014年出品的基于 Docker 的集群管理调度工具,能够将多台主机构建成一个Docker集群,并结合Overlay网络实现容器调度的互访 用户可以只通过 Swarm API 来管理多个主机上的 Docker Swarm 群集包…...

Python | Leetcode Python题解之第335题路径交叉
题目: 题解: class Solution:def isSelfCrossing(self, distance: List[int]) -> bool:n len(distance)# 处理第 1 种情况i 0while i < n and (i < 2 or distance[i] > distance[i - 2]):i 1if i n:return False# 处理第 j 次移动的情况…...

Ubuntu视频工具
1. VLC VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影音光…...

HBase snapshot+replication 测试
一、背景 画像标签服务(CDP)是核心服务,被公司其他系统如现金、电商、风控等核心业务调用。异常的话,影响范围大。 二、目标 存量数据测试通过 snapshot 迁移。增量数据测试通过 replication 同步。 三、测试 方案二测试&#x…...

代码随想录算法训练营第四十一天|图论基础、深度优先搜索理论基础、98. 所有可达路径、797. 所有可能的路径
图论基础 图的种类:有向图 和 无向图,加权有向图, 加权无向图 无向图中有几条边连接该节点,该节点就有几度。 在有向图中,每个节点有出度和入度。出度:从该节点出发的边的个数。入度:指向该节…...

STM32学习笔记09-SPI通信
目录 SPI通信简介 硬件电路 移位示意图 SPI基本时序单元 SPI时序 W25Q64简介 硬件电路 W25Q64框图 Flash操作注意事项 SPI外设简介 SPI框图 SPI基本结构 主模式全双工连续传输 非连续传输 软件/硬件波形对比 SPI应用 软件SPI读写W25Q64 硬件SPI读写W25Q64 SP…...

树------二叉树
什么是树: 树是一种特殊的结构,由多个节点连接构成,并且不包含回路,也可以认为树是不包含回路的无向连通图,具体如下图所示。 当我们要确定一棵树的形态时,要指定一个根节点,没有父亲节点的节点…...
如何对加密后的数据进行模糊查询(面试题)
目录 前言1. 基本知识2. 国内做法 前言 这道题在面试比较常见,但是在算法逻辑层面中,直接对加密数据进行模糊查询是不可行的,因为加密算法会使数据变成不可读的形式 需要在加密过程中采取特殊的策略来支持模糊查询 以下只是结合网上现有的资…...
【MYSQL】当前读和快照读
前言 复习下隔离级别: 1、读未提交:一个事务还没提交时,它做的变更就能被别的事务看到。 2、读提交:一个事务提交之后,它做的变更会被其他事务看到 3、可重复读:一个事务执行过程中看到的数据,…...
C语言-使用数组法,指针法实现将一个5X5的矩阵中最大的元素放在中心,四个角分别放四个最小的元素(顺序为从左到右,从上到下,从小到大存放),写一函数实现之。
1.题目要求: 将一个5X5的矩阵中最大的元素放在中心,四个角分别放四个最小的元素(顺序为从左到右,从上到下,从小到大存放),写一函数实现之。 2.数组法实现 #define _CRT_SECURE_NO_WARNINGS 1…...

Android gradle 构建
Understanding Tasks - Gradle task kapt 是 Kotlin 语言的注解处理器,它是 Android Studio 中用于处理 Kotlin 注解的工具。它通过在编译期间生成代码来增强 Kotlin 代码的功能。需要 Kotlin 编译器来解析和处理注解;使用 APT 来生成代码,…...

vulnhub系列:devguru
vulnhub系列:devguru 靶机下载 一、信息收集 nmap扫描存活,根据mac地址寻找IP nmap 192.168.23.0/24nmap扫描端口,开放端口:22、80、8585 nmap 192.168.23.147 -p- -sV -Pn -O访问80端口 dirb目录扫描,存在 git 源…...
Robot Operating System——高质量图像传输
大纲 应用场景定义字段解释 案例 sensor_msgs::msg::Image 是 ROS (Robot Operating System) 中的一个消息类型,用于表示未压缩的图像数据。它通常用于传输和处理高质量的图像数据。 应用场景 机器人视觉 图像处理:在机器人视觉系统中,未压缩…...

NLP_情感分类_预训练加微调方案
文章目录 项目背景代码导包一些模型以及训练的参数设置定义dataset定义模型读取数据声明训练及测试数据集将定义模型实例化打印模型结构模型训练测试集效果 同类型项目 项目背景 项目的目的,是为了对情感评论数据集进行预测打标。在训练之前,需要对数据…...

全网最适合入门的面向对象编程教程:36 Python的内置数据类型-字典
全网最适合入门的面向对象编程教程:36 Python 的内置数据类型-字典 摘要: 字典是非常好用的容器,它可以用来直接将一个对象映射到另一个对象。一个拥有属性的空对象在某种程度上说就是一个字典,属性名映射到属性值。在内部&#…...

DataWind看板绘制案例
摘要: 1. 在不清楚DataWind看板怎么画的情况,可以先把表格给实现了,然后找几个有价值的数据进行看板实现 2. 还是不知道怎么画的情况,就去模仿其他人的案例; 3. 多看看DataWind提供的函数用法,就可以把表达式的使用运用起来了; 飞书官方文档:https://www.volcen…...

Golang | Leetcode Golang题解之第335题路径交叉
题目: 题解: func isSelfCrossing(distance []int) bool {n : len(distance)// 处理第 1 种情况i : 0for i < n && (i < 2 || distance[i] > distance[i-2]) {i}if i n {return false}// 处理第 j 次移动的情况if i 3 && di…...

C# 在Word中插入或删除分节符
在Word中,分节符是一种强大的工具,用于将文档分成不同的部分,每个部分可以有独立的页面设置,如页边距、纸张方向、页眉和页脚等。正确使用分节符可以极大地提升文档的组织性和专业性,特别是在长文档中,需要…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...