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

漫谈设计模式 [16]:中介者模式

引导性开场

菜鸟:老鸟,我最近在开发一个聊天应用的时候遇到了点问题。每个用户都需要与其他用户直接通信,这让我在代码中写了很多复杂的逻辑来管理这些联系。这样下去,代码越来越难维护了。你有什么建议吗?

老鸟:嗯,这确实是个常见的问题。你有没有听说过中介者模式?

菜鸟:中介者模式?没听过。它能解决我现在的问题吗?

老鸟:绝对可以。让我给你详细解释一下。

渐进式介绍概念

老鸟:我们可以用一个简单的生活例子来理解中介者模式。想象一下,你在一个公司工作,公司里有很多同事。如果每个同事都需要直接和其他所有同事沟通,整个沟通过程会非常混乱,对吧?

菜鸟:对啊,人越多越难管理。

老鸟:所以,公司通常会有一个中介——比如一个经理。所有的沟通都通过经理来进行。同事A想和同事B沟通,他只需要告诉经理,经理再去通知同事B。这样,沟通就变得简单和有序了。这就是中介者模式的核心思想。

菜鸟:哦,我明白了。中介者模式是通过一个中介来简化对象之间的通信。

Python代码示例,逐步展开

老鸟:让我们通过一个简单的 Python 示例来进一步理解吧。

基础实现

老鸟:首先,我们来看看没有中介者模式的实现。假设我们有两个用户,每个用户都可以直接向另一个用户发送消息。

class User:def __init__(self, name):self.name = nameself.contacts = []def add_contact(self, user):self.contacts.append(user)def send_message(self, message, to_user):print(f"{self.name} sends message to {to_user.name}: {message}")to_user.receive_message(message, self)def receive_message(self, message, from_user):print(f"{self.name} received message from {from_user.name}: {message}")# 创建用户
alice = User("Alice")
bob = User("Bob")# 添加联系人
alice.add_contact(bob)
bob.add_contact(alice)# 发送消息
alice.send_message("Hello, Bob!", bob)
bob.send_message("Hi, Alice!", alice)

菜鸟:这样每个用户都需要知道其他用户的存在,这确实不太好。

老鸟:没错,现在我们来引入中介者模式。

引入中介者模式

老鸟:我们创建一个 ChatRoom 类作为中介者,让所有用户通过 ChatRoom 来通信。

class ChatRoom:def show_message(self, user, message):print(f"{user.name} says: {message}")class User:def __init__(self, name, chatroom):self.name = nameself.chatroom = chatroomdef send_message(self, message):self.chatroom.show_message(self, message)# 创建中介者
chatroom = ChatRoom()# 创建用户
alice = User("Alice", chatroom)
bob = User("Bob", chatroom)# 发送消息
alice.send_message("Hello, Bob!")
bob.send_message("Hi, Alice!")

菜鸟:这样看起来确实更简洁了。用户只需要知道 ChatRoom,而不需要直接引用其他用户。

问题与反思

菜鸟:可是,如果我想在发送消息时包含一些业务逻辑,比如对某些消息进行过滤,该怎么办?

老鸟:好问题。你可以在 ChatRoom 中添加相应的逻辑,这样所有的消息处理都集中在一个地方,代码更容易维护和扩展。

class ChatRoom:def show_message(self, user, message):if self.message_filter(message):print(f"{user.name} says: {message}")else:print(f"Message from {user.name} was blocked.")def message_filter(self, message):# 简单的示例过滤器return "spam" not in message.lower()# 使用新的 ChatRoom
chatroom = ChatRoom()alice = User("Alice", chatroom)
bob = User("Bob", chatroom)alice.send_message("Hello, Bob!")
bob.send_message("This is spam message.")

菜鸟:明白了,这样我就可以在 ChatRoom 中集中处理所有的业务逻辑了。

优势与适用场景

老鸟:中介者模式有很多优势。它可以减少对象之间的耦合,使系统更易于扩展和维护。适用于对象之间有复杂交互的情况,比如聊天系统、GUI组件之间的通信等等。

菜鸟:明白了,这样在需要扩展用户数量或者添加新功能的时候,就不需要修改每个用户的代码了。

常见误区与优化建议

老鸟:不过要注意,不要把所有的逻辑都塞到中介者里,否则中介者会变得过于复杂。可以通过拆分中介者或引入其他设计模式来保持代码的清晰和简洁。

菜鸟:好的,我会注意的。

总结与延伸阅读

老鸟:总结一下,中介者模式通过引入一个中介者对象,来简化对象之间的通信和交互。它有助于减少对象之间的耦合,使系统更容易扩展和维护。你可以查阅《设计模式:可复用面向对象软件的基础》这本书,里面有更多设计模式的详细解释。

菜鸟:谢谢老鸟,我会去读一读的。下次我还想学习其他设计模式,你有什么推荐吗?

老鸟:你可以先了解一下观察者模式和策略模式,这两个模式也非常常用而且很有趣。

菜鸟:好的,我会去研究一下的。再次感谢!

相关文章:

漫谈设计模式 [16]:中介者模式

引导性开场 菜鸟:老鸟,我最近在开发一个聊天应用的时候遇到了点问题。每个用户都需要与其他用户直接通信,这让我在代码中写了很多复杂的逻辑来管理这些联系。这样下去,代码越来越难维护了。你有什么建议吗? 老鸟&…...

深度学习-物体检测YOLO(You only look once)

目录 一:YOLO算法的网络结构 流程 1.图像分割 2.图片在网格中的处理 3.非极大值抑制 二:训练 三:分类误差 四:与Faster R-CNN对比 一:YOLO算法的网络结构 GooleNet4个卷积2个全连接层 流程 输入原始图片resize到…...

redisson中的分布式锁

我的博客大纲 我的后端学习大纲 a.redisson概述: 1.Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)2.redisson介绍官方文档地址:3.Redisson它不仅提供了一系列的分布式的Java常用对象,还…...

如何将镜像推送到docker hub

前言 这一篇应该是最近最后一篇关于docker的博客了,咱来个有始有终,将最后一步——上传镜像给他写完,废话不多说,直接进入正题。 登录 首先需要确保登录才能推送到你的仓库中去,在终端输入docker login,输入用户名和…...

GO 匿名函数

GO 匿名函数 文章目录 GO 匿名函数1. **回调函数**2. **goroutine 中的操作**3. **延迟操作(defer)**4. **内联处理逻辑**5. **闭包**6. **过滤、映射等函数式编程风格**7. **测试中的临时逻辑**8. **短期存在的逻辑操作**总结 匿名函数在 Go 语言中的使…...

JuiceFS 在多云架构中加速大模型推理

在大模型的开发与应用中,数据预处理、模型开发、训练和推理构成四个关键环节。本文将重点探讨推理环节。在之前的博客中,社区用户 BentoML 和贝壳的案例提到了使用 JuiceFS 社区版来提高模型加载的效率。本文将结合我们的实际经验,详细介绍企…...

【DCL】Dual Contrastive Learning for General Face Forgery Detection

文章目录 Dual Contrastive Learning for General Face Forgery Detectionkey points:贡献方法数据视图生成对比学习架构实例间对比学习实例内对比学习总损失函数实验实验细节定量结果跨数据集评估跨操作评估消融实验可视化Dual Contrastive Learning for General Face Forgery…...

https的特点

https的特点 优点:缺点:HTTPS是如何保证安全的? 优点: 使用HTTPS协议可以认证用户和服务器,确保数据发送到正确的客户端和服务器;使用HTTPS协议可以进行加密传输、身份认证,通信更加安全、防止…...

〖open-mmlab: MMDetection〗解析文件:mmdet/models/losses/cross_entropy_loss.py

目录 深入解析MMDetection中的CrossEntropyLoss及其应用1. 概述2. 核心函数2.1 cross_entropy2.1.1 函数定义和参数说明2.1.2 函数体2.1.3 总结 2.2 binary_cross_entropy2.2.1 _expand_onehot_labels函数2.2.2 binary_cross_entropy函数2.2.3 总结 2.3 mask_cross_entropy2.3.…...

【PyTorch单点知识】torch.nn.Embedding模块介绍:理解词向量与实现

文章目录 0. 前言1. 基础介绍1.1 基本参数1.2 可选参数1.3 属性1.4 PyTorch源码注释 2. 实例演示3. embedding_dim的合理设定4. 结论 0. 前言 按照国际惯例,首先声明:本文只是我自己学习的理解,虽然参考了他人的宝贵见解及成果,但…...

Jedis 操作 Redis 数据结构全攻略

Jedis 操作 Redis 数据结构全攻略 一 . 认识 RESP二 . 前置操作2.1 创建项目2.2 关于开放 Redis 端口的问题2.2.1 端口转发?2.2.2 端口配置 2.3 连接到 Redis 服务器 三 . 通用命令3.1 set 和 get3.2 exists 和 del3.3 keys3.4 expire、ttl、type 三 . string 相关命令3.1 mse…...

ctf.show靶场ssrf攻略

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 web351 解析:post传入url参数他就会访问。 解法: hackbar传入url参数写入https://127.0.0.1/flag.php web352 解析:post传入url参数,不能是127.0.0.1和localhost 解法:缩写127.1传入 web353 解析…...

在 PyTorch 中,如何使用 `pack_padded_sequence` 来提高模型训练的效率?

在PyTorch中,pack_padded_sequence 是一个非常有用的函数,它可以用来提高模型训练的效率,特别是在处理变长序列数据时。这个函数的主要作用是将填充后的序列数据打包,以便循环神经网络(RNN)可以更高效地处理…...

Gossip协议

主要用在Redis Cluster 节点间通信 Gossip协议,也称为流行病协议(Epidemic Protocol),是一种在分布式系统中用于信息传播和故障探测的算法。 一、工作原理 随机选择传播对象 每个节点会定期随机选择一些其他节点作为传播对象。这…...

数据结构————双向链表

内存泄漏: 内存泄漏(Memory Leak)是指程序中已动态分配的内存由于某种原因程序未释放或无法释放,导致系统内存的浪费,严重时会导致程序运行缓慢甚至崩溃。这种情况在长时间运行的程序或大型系统中尤为常见&#xff0c…...

55 - I. 二叉树的深度

comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9855%20-%20I.%20%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%B7%B1%E5%BA%A6/README.md 面试题 55 - I. 二叉树的深度 题目描述 输入一棵二叉树的根节点…...

Redis——初识Redis

初识Redis Redis认识Redis 分布式系统单机架构为什么要引入分布式理解负载均衡数据库的读写分离引入主从数据库 引入缓存数据库分库分表业务拆分——微服务常见概念了解 Redis背景介绍特性应用场景Redis不能做的事情Redis客户端redis客户端的多种形态 Redis 认识Redis 存储数…...

Xshell or Xftp提示“要继续使用此程序,您必须应用最新的更新或使用新版本”

Xshell提示“要继续使用此程序,您必须应用最新的更新或使用新版本”,笔者版本是xshell 6 方法一:更改系统时间 对于Windows 10用户,首先找到系统日期,右键点击并选择“调整时间/日期”。将日期设定为上一年。完成调整后&#x…...

table用position: sticky固定多层表头,滑动滚动条border边框透明解决方法

问题:我发现,这个上下滑动有内容经过就会出现如图的情况。 解决的方法:用outline(轮廓)替代border,以达到我们想要的样式。 outline主要是在元素边框的外围设置轮廓,outline不占据空间,绘制于…...

基于飞桨paddle2.6.1+cuda11.7+paddleRS开发版的目标提取-道路数据集训练和预测代码

基于飞桨paddle2.6.1cuda11.7paddleRS开发版的目标提取-道路数据集训练和预测代码 预测结果: 预测影像: (一)准备道路数据集 下载数据集地址: https://aistudio.baidu.com/datasetdetail/56961 mass_road.zip …...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter

java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用&#xff08;Math::max&#xff09; 2 函数接口…...

ZYNQ学习记录FPGA(二)Verilog语言

一、Verilog简介 1.1 HDL&#xff08;Hardware Description language&#xff09; 在解释HDL之前&#xff0c;先来了解一下数字系统设计的流程&#xff1a;逻辑设计 -> 电路实现 -> 系统验证。 逻辑设计又称前端&#xff0c;在这个过程中就需要用到HDL&#xff0c;正文…...

二叉树-144.二叉树的前序遍历-力扣(LeetCode)

一、题目解析 对于递归方法的前序遍历十分简单&#xff0c;但对于一位合格的程序猿而言&#xff0c;需要掌握将递归转化为非递归的能力&#xff0c;毕竟递归调用的时候会调用大量的栈帧&#xff0c;存在栈溢出风险。 二、算法原理 递归调用本质是系统建立栈帧&#xff0c;而非…...

Qt/C++学习系列之列表使用记录

Qt/C学习系列之列表使用记录 前言列表的初始化界面初始化设置名称获取简单设置 单元格存储总结 前言 列表的使用主要基于QTableWidget控件&#xff0c;同步使用QTableWidgetItem进行单元格的设置&#xff0c;最后可以使用QAxObject进行单元格的数据读出将数据进行存储。接下来…...

SDU棋界精灵——硬件程序ESP32实现opus编码

一、 ​​音频处理框架​ 该项目基于Espressif的音频处理框架构建,核心组件包括 ESP-ADF 和 ESP-SR,以下是完整的音频处理框架实现细节: 1.核心组件 (1) 音频前端处理 (AFE - Audio Front-End) ​​main/components/audio_pipeline/afe_processor.c​​功能​​: 声学回声…...