中介者模式(Mediator Pattern)、桥接模式(Bridge Pattern) 和 策略模式(Strategy Pattern)
中介者模式(Mediator Pattern)、桥接模式(Bridge Pattern) 和 策略模式(Strategy Pattern) 都是常见的设计模式,它们解决不同类型的问题。我们将通过 Swift 示例来说明它们的使用场景,并附上简洁的图示。
1. 中介者模式(Mediator Pattern)
目的:中介者模式通过引入一个中介者对象,来减少类与类之间的直接耦合,避免多对多的依赖关系,使得系统中的类之间通过中介者进行交互。
使用场景:
- 当多个类之间的交互复杂且不易管理时,通过引入中介者模式可以减少各个类之间的依赖关系。
- 适用于 UI 组件之间的交互,例如聊天系统中多个用户的消息传递,或多个模块之间的消息通知。
Swift 示例:
假设我们有一个聊天系统,多个用户之间互相发送消息,使用中介者来协调消息的传递:
// 中介者协议
protocol ChatMediator {func sendMessage(_ message: String, from user: User)func addUser(_ user: User)
}// 用户类
class User {let name: Stringvar mediator: ChatMediator?init(name: String) {self.name = name}func sendMessage(_ message: String) {mediator?.sendMessage(message, from: self)}func receiveMessage(_ message: String) {print("\(name) received message: \(message)")}
}// 中介者实现
class ChatRoom: ChatMediator {private var users: [User] = []func addUser(_ user: User) {users.append(user)user.mediator = self}func sendMessage(_ message: String, from user: User) {for u in users where u !== user {u.receiveMessage(message)}}
}// 使用中介者模式
let chatRoom = ChatRoom()let user1 = User(name: "Alice")
let user2 = User(name: "Bob")
let user3 = User(name: "Charlie")chatRoom.addUser(user1)
chatRoom.addUser(user2)
chatRoom.addUser(user3)user1.sendMessage("Hello, everyone!") // Alice 发送消息,Bob 和 Charlie 会收到消息
图示:
+------------+| ChatRoom |+------------+|+---------+----------+| | |
+---+ +---+ +---+
| A | | B | | C |
+---+ +---+ +---+
2. 桥接模式(Bridge Pattern)
目的:桥接模式的核心思想是将抽象与实现分离,使得二者可以独立扩展。通过桥接模式,你可以将类的功能分解为多个维度的类,并将这些维度的类组合起来,减少子类的数量。
使用场景:
- 当你需要将一个类的抽象部分与其实现部分解耦,使得二者可以独立地变化时。
- 适用于设备控制系统、图形绘制系统等场景。
Swift 示例:
假设我们有一个图形绘制系统,需要同时支持不同的形状(如圆形、方形)和不同的绘制方式(如矢量绘制、位图绘制):
// 实现接口
protocol DrawingAPI {func drawCircle(radius: Double)
}// 不同的绘制方式(实现)
class VectorDrawing: DrawingAPI {func drawCircle(radius: Double) {print("Drawing a vector circle with radius \(radius)")}
}class RasterDrawing: DrawingAPI {func drawCircle(radius: Double) {print("Drawing a raster circle with radius \(radius)")}
}// 抽象部分
protocol Shape {var drawingAPI: DrawingAPI { get }func draw()
}// 圆形类
class Circle: Shape {var drawingAPI: DrawingAPIvar radius: Doubleinit(drawingAPI: DrawingAPI, radius: Double) {self.drawingAPI = drawingAPIself.radius = radius}func draw() {drawingAPI.drawCircle(radius: radius)}
}// 使用桥接模式
let vectorDrawing = VectorDrawing()
let rasterDrawing = RasterDrawing()let circle1 = Circle(drawingAPI: vectorDrawing, radius: 5)
circle1.draw() // 输出: Drawing a vector circle with radius 5let circle2 = Circle(drawingAPI: rasterDrawing, radius: 10)
circle2.draw() // 输出: Drawing a raster circle with radius 10
图示:
+------------------+| Shape |+------------------+^|+------------+| Circle |+------------+|+-------------+| DrawingAPI |+-------------+/ \/ \
+--------+ +--------+
| Vector | | Raster |
+--------+ +--------+
3. 策略模式(Strategy Pattern)
目的:策略模式用于将一系列的算法封装起来,让它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端。
使用场景:
- 当你有多种算法,且希望在运行时决定使用哪种算法时。
- 适用于需要动态选择算法或者行为的场景,比如支付方式选择、排序策略等。
Swift 示例:
假设我们有一个应用,允许用户选择不同的排序算法:
图示:
// 排序策略协议
protocol SortStrategy {func sort(_ data: [Int]) -> [Int]
}// 具体的排序算法
class QuickSort: SortStrategy {func sort(_ data: [Int]) -> [Int] {return data.sorted()}
}class MergeSort: SortStrategy {func sort(_ data: [Int]) -> [Int] {return data.sorted()}
}class BubbleSort: SortStrategy {func sort(_ data: [Int]) -> [Int] {var array = datafor i in 0..<array.count {for j in 0..<array.count-i-1 {if array[j] > array[j+1] {array.swapAt(j, j+1)}}}return array}
}// Context 使用策略模式
class SortContext {private var strategy: SortStrategyinit(strategy: SortStrategy) {self.strategy = strategy}func setStrategy(_ strategy: SortStrategy) {self.strategy = strategy}func executeStrategy(data: [Int]) -> [Int] {return strategy.sort(data)}
}// 使用策略模式
let context = SortContext(strategy: QuickSort())let data = [5, 2, 9, 1, 5, 6]
let sortedData = context.executeStrategy(data: data)
print(sortedData) // 输出: [1, 2, 5, 5, 6, 9]// 切换排序算法
context.setStrategy(BubbleSort())
let bubbleSortedData = context.executeStrategy(data: data)
print(bubbleSortedData) // 输出: [1, 2, 5, 5, 6, 9]
lua
+-----------------+| SortContext |+-----------------+|+-------+--------+| |
+-----------+ +-----------+
| QuickSort | | BubbleSort |
+-----------+ +-----------+| |+------------+ +------------+| MergeSort | | SortStrategy|+------------+ +------------+
总结对比表:
| 模式 | 目的/特点 | 使用场景 | Swift 示例 |
|---|---|---|---|
| 中介者模式 | 降低类之间的耦合,通过中介者来协调交互 | 多个对象之间存在复杂交互时,避免直接引用其他对象 | 聊天系统中用户通过中介者交换消息 |
| 桥接模式 | 将抽象和实现分离,允许它们独立变化 | 抽象部分和实现部分变化频繁的场景 | 图形绘制系统,不同的形状和绘制方式 |
| 策略模式 | 将算法封装成独立的策略类,使得算法可以互换 | 需要根据不同情境使用不同算法的场景 | 排序算法的选择,可以动态切换不同的排序策略 |
这些设计模式帮助解决不同类型的耦合问题,允许我们编写更加灵活、可扩展、可维护的代码。根据实际需求选择合适的模式,可以提升代码的可维护性和复用性。
相关文章:
中介者模式(Mediator Pattern)、桥接模式(Bridge Pattern) 和 策略模式(Strategy Pattern)
中介者模式(Mediator Pattern)、桥接模式(Bridge Pattern) 和 策略模式(Strategy Pattern) 都是常见的设计模式,它们解决不同类型的问题。我们将通过 Swift 示例来说明它们的使用场景࿰…...
客户案例:基于慧集通打通聚水潭电商ERP与用友U8系统集成之路
一、引言 本原型客户是 生物科技公司,其公司系列抗菌抗病毒产品广泛应用于医疗用品、纺织服饰、家纺用品、母婴护理、女性用品、个人防护等多个领域。在知识产权方面,公司在专业领域已获得商标和专利近百项,创新能力得到了国家及行业内普遍认…...
阿里云clb是什么
传统型负载均衡服务 阿里云CLB(Classic Load Balancer)是阿里云提供的一种传统型负载均衡服务,主要用于将访问流量根据转发策略分发到后端多台云服务器。 CLB的定义和功能 CLB是一种流量分发控制服务,通过设置虚拟服务地…...
【Cursor编辑器】自用经验和实操(迭代更新)
1.启动composer crtl I 2.生成直接一直问加载 3. 实操 生成个知识图谱,使用csv文件里面的数据创关系和节点。...
【学习笔记】ChatGPT原理与应用开发——基础科普
HuggingLLM(ChatGPT原理与应用开发) 原文链接:HuggingLLM(ChatGPT原理与应用开发)-课程详情 | Datawhale 此处仅为学习记录和总结 1:基础科普 1.1:自然语言背景 图灵测试 如果一个人&#x…...
基于Web的实验中心工作管理网站的设计与实现
写作任务 一、课题背景 实验中心承担了全校计算机公共基础课程和学院专业课程,需要对实验中心工作进行有效的管理。 二、课题任务 本课题设计和实现实验中心工作管理系统。 系统的主要内容包括: (1)人员管理; &am…...
docker 安装minio
docker pull minio/minio #启动 mkdir -p /root/minio/config mkdir -p /root/minio/datadocker run -d \--name minio \-p 9002:9000 \-p 9001:9001 \--restartalways \-v /root/minio/data:/data \-v /root/minio/config:/root/.minio \-e "MINIO_ACCESS_KEYminioadmin…...
ubuntu下ipmi的使用(4028)
参考ubuntu系统下配置IPMI_ubuntu ipmi-CSDN博客 参考:ipmitool ubuntu 安装_ipmi centos ubuntu使用总结-CSDN博客 1.安装 sudo apt-get -y install ipmitool 2.加载 modprobe ipmi_msghandlermodprobe ipmi_devintfmodprobe ipmi_si 3.使用,查看不到的话&am…...
周记-唐纳德的《计算机程序设计艺术》
用代码生成代码 开发一个协议,字段有些多,每个字段是QT的属性,需要写Q_PROPERTY,一个一个编辑的话比较繁琐,耗费时间。后来就用代码生成了头文件和源文件,get和set还有signal函数,内容基本都是…...
极品飞车6的快捷键与车辆等级
极品飞车,英文全称为Need for Speed,是EA公司于1994年开始研发的赛车类竞技游戏。从1996年的《极品飞车-特别版》、2002年的《极品飞车:闪电追踪2》、2005年的《极品飞车:地下狂飙2》、到2024年《极品飞车:集结》,是70后、80年、90年等几代人…...
计算机毕业设计Python+知识图谱大模型AI医疗问答系统 健康膳食推荐系统 食谱推荐系统 医疗大数据 机器学习 深度学习 人工智能 爬虫 大数据毕业设计
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
纯真社区版IP库CZDB数据格式使用教程
1. 概述 纯真社区版IP库是一种免费且公开的IP地理位置数据库,主要面向非商业用途。其最新推出的CZDB格式是一种全新的数据文件格式,自2024年10月起将成为官方维护和更新的唯一版本。该格式支持同时存储IPv4和IPv6地址信息,具备以下优点&…...
Linux(Centos 7.6)软件包安装
Linux软件安装,常见的有三种方式,rpm方式、yum方式、源码编译安装方式。其中rpm方式可能存在依赖方式,可能会比较麻烦;源码编译安装同样可能会缺少一些编译需要的软件需要安装,也会比较麻烦;相对比较好的方…...
[WASAPI]音频API:从Qt MultipleMedia走到WASAPI,相似与不同
[WASAPI] 从Qt MultipleMedia 来看WASAPI 最近在学习有关Windows上的音频驱动相关的知识,在正式开始说WASAPI之前,我想先说一说Qt的Multiple Media,为什么呢?因为Qt的MultipleMedia实际上是WASAPI的一层封装,它在是线…...
【畅购商城】微信支付之支付模块
目录 支付页面 接口 后端实现 前端实现 支付页面 步骤一:创建 flow3.vue组件 步骤二:引入第三方资源(js、css) <script> import TopNav from ../components/TopNav import Footer from …...
网络安全专有名词详解_2
57.Webshell 就是以ASP、php、jsp、cgi等网页文件形式存在的一种命令执行环境,也叫做网页的后门,可以上传下载文件,查看数据库和执行任意的程序命令等。 58.跨站攻击 XSS,是指攻击者利用网站程序对用户输入过滤不足,输…...
【传感器技术与应用】第2章 基本电量传感器,电位器式传感器,电感式传感器,电容式传感器
注作者了解更多 我的其他CSDN专栏 毕业设计 求职面试 大学英语 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数…...
【day20】集合深入探讨
模块19回顾 在深入探讨模块20之前,让我们回顾一下day19中的关键内容: Collection集合:单列集合的顶级接口,提供了add、addAll、clear、size、isEmpty、remove、toArray、contains等方法。迭代器(Iterator)…...
【英语语法】用must表对过去推测时,要用完成时must have been / must have done(不能直接用过去时)
文章目录 疑问解释1. 表达过去的推测2. 与时态一致3. 语法结构的限制4. 例子对比总结 疑问 This must have been a year-round activity as no structures have been found which would have been used to shelter animals in the winter. 为什么must表示对过去推测要用完成时&…...
数值计算期末考试重点(一)(黄云清版教材)
1.误差的分类 2.绝对误差和绝对误差限 3.绝对误差和绝对误差限 例题(课后习题1.2) 4.有效数字 例题(课后习题1.6) 5.算法的数值稳定性 例题(课后习题1.9) 这个手算比较艰难,还是给计算机算吧&am…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...
WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
Windows 下端口占用排查与释放全攻略
Windows 下端口占用排查与释放全攻略 在开发和运维过程中,经常会遇到端口被占用的问题(如 8080、3306 等常用端口)。本文将详细介绍如何通过命令行和图形化界面快速定位并释放被占用的端口,帮助你高效解决此类问题。 一、准…...
[特殊字符] Spring Boot底层原理深度解析与高级面试题精析
一、Spring Boot底层原理详解 Spring Boot的核心设计哲学是约定优于配置和自动装配,通过简化传统Spring应用的初始化和配置流程,显著提升开发效率。其底层原理可拆解为以下核心机制: 自动装配(Auto-Configuration) 核…...
