中介者模式(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 示例
中介者模式降低类之间的耦合,通过中介者来协调交互多个对象之间存在复杂交互时,避免直接引用其他对象聊天系统中用户通过中介者交换消息
桥接模式将抽象和实现分离,允许它们独立变化抽象部分和实现部分变化频繁的场景图形绘制系统,不同的形状和绘制方式
策略模式将算法封装成独立的策略类,使得算法可以互换需要根据不同情境使用不同算法的场景排序算法的选择,可以动态切换不同的排序策略

这些设计模式帮助解决不同类型的耦合问题,允许我们编写更加灵活、可扩展、可维护的代码。根据实际需求选择合适的模式,可以提升代码的可维护性和复用性。

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

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

相关文章

阿尔萨斯(JVisualVM)JVM监控工具

文章目录 前言阿尔萨斯(JVisualVM)JVM监控工具1. 阿尔萨斯的功能2. JVisualVM启动3. 使用 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff…

<数据集>芝麻作物和杂草识别数据集<目标检测>

数据集下载链接 &#xff1c;数据集&#xff1e;芝麻作物和杂草识别数据集&#xff1c;目标检测&#xff1e;https://download.csdn.net/download/qq_53332949/90181548数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;1300张 标注数量(xml文件个数)&#xff1a;130…

STM32-笔记18-呼吸灯

1、实验目的 使用定时器 4 通道 3 生成 PWM 波控制 LED1 &#xff0c;实现呼吸灯效果。 频率&#xff1a;2kHz&#xff0c;PSC71&#xff0c;ARR499 利用定时器溢出公式 周期等于频率的倒数。故Tout 1/2KHZ&#xff1b;Ft 72MHZ PSC71&#xff08;喜欢设置成Ft的倍数&…

【Java】接口多态练习题

设计一个USB接口&#xff0c;USB接口拥有启动和停止方法&#xff0c;网卡类实现USB接口&#xff0c;重写实现网卡启动停止方法 声卡类实现USB接口&#xff0c;重写实现声卡启动和停止方法&#xff0c; 主板类拥有使用USB接口的方法。方法接收USB接口类型或子类型&#xff0c;方…

JVM实战—4.JVM垃圾回收器的原理和调优

大纲 1.JVM的新生代垃圾回收器ParNew如何工作 2.JVM老年代垃圾回收器CMS是如何工作的 3.线上部署系统时如何设置垃圾回收相关参数 4.新生代垃圾回收参数如何优化 5.老年代的垃圾回收参数如何优化 6.问题汇总 1.JVM的新生代垃圾回收器ParNew如何工作 (1)JVM的核心运行原理…

E-commerce .net+React(一)——项目初始化

文章目录 项目地址一、创建.Net环境1.1环境配置1.1.1 使用vscode创建webapi1.1.2 Clean architecture结构创建1.1.3 将创建好结构的项目添加到git里1.1.4 EF Core配置1. 在infrastructure里安装EF所需环境2. 创建Product数据模型3. 创建EF Core的DbContext 数据库上下文4. 创建…

lua和C API库一些记录

相关头文件解释 lua.h&#xff1a;声明lua提供的基础函数&#xff0c;所有内容都有个前缀lua_&#xff1b; luaxlib.h&#xff1a;声明辅助库提供的函数&#xff0c;所有内容都有个前缀luaL_&#xff1b; lualib.h&#xff1a;声明了打开标准库的函数&#xff1b; 辅助库对…

elasticsearch-java客户端jar包中各模块的应用梳理

最近使用elasticsearch-java客户端实现对elasticsearch服务的Api请求&#xff0c;现对elasticsearch-java客户端jar包中各模块的应用做个梳理。主要是对co.elastic.clients.elasticsearch路径下的各子包的简单说明。使用的版本为&#xff1a;co.elastic.clients:elasticsearch-…

机器学习 LightGBM 算法原理解析

摘要&#xff1a; 本文深入探讨机器学习中的 LightGBM 算法&#xff0c;从其基本概念出发&#xff0c;详细阐述了核心原理&#xff0c;包括直方图算法、单边梯度采样、互斥特征捆绑等关键技术&#xff0c;对比分析了与传统 GBDT 算法的差异&#xff0c;还介绍了参数调优策略及在…

vscode实用插件(持续更新)

目录 Git History Diff Git Graph Error Lens Git History Diff 用于将当前分支的某个文件夹与远程分支的相同文件夹做对比&#xff0c;方便代码评审&#xff01;解决了为了一个问题而多次commit&#xff0c;导致代码不好评审&#xff0c;即不晓得和远程分支相比&#xff0…

full-stack-fastapi-template postgres 管理系统安装指南

full-stack-fastapi-template postgres 管理系统安装指南 本项目基于 full-stack-fastapi-template 模板开发 1. 环境准备 请确保您的系统已安装以下软件&#xff1a; Python 3.9 Node.js 16 PostgreSQL 13 Git Docker (可选&#xff0c;用于容器化部署) 2. 获取代码 # 2.…

关于window.open 被浏览器拦截解决方案

分析原因 当浏览器检测到非用户操作产生的新弹出窗口时&#xff0c;会对其进行阻止&#xff0c;因为浏览器认为这可能是广告&#xff0c;不是用户期望的页面。 注意&#xff1a; 如果 window.open 是在用户触发事件&#xff08;如点击事件&#xff09;或页面加载时调用&#…

并发编程-AQS

AQS 什么是AQS java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为&#xff0c;比如等待队列、条件队列、独占获取、共享获取等&#xff0c;而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个同步框架&#xff0c;可以用来实现…

Prompt提示工程上手指南(七)Prompt编写实战-基于智能客服问答系统下的Prompt编写

前言 本系列文章从最初的基础原理与入门实践切入&#xff0c;一直延伸到主流策略、引导策略、RAG&#xff08;检索增强生成&#xff09;、思维树&#xff08;ToT&#xff09;与避免幻觉&#xff08;Hallucination&#xff09;的策略这种渐进的结构方便了对初学者和进阶者的双向…

mac系统vsCode中使用Better Comments在.vue文件里失效

问题&#xff1a;关于Better Comments默认在html、TS、JS中有效&#xff0c;在vue中无效,需要单独进行配置 windows系统可以参考友链Better Comments&#xff08;注释高亮&#xff09;在vue文件里失效的问题 关于Better Comments电脑的配置路径&#xff1a; Windows系统&…

探索 JavaBean(实体类)的奇妙世界

目录 一、啥是 JavaBean&#xff08;实体类&#xff09; &#xff08;一&#xff09;定义与特点 &#xff08;二&#xff09;为啥要用 JavaBean 二、动手写一个 JavaBean&#xff08;实体类&#xff09; &#xff08;一&#xff09;创建一个简单的用户 JavaBean &#xf…

mac中idea中英文版本切换

1.快捷键command&#xff0c;或者 2.找到插件&#xff08;plugins&#xff09;&#xff0c;搜索chinese&#xff0c;安装 第一次安装好点击应用会提示重启&#xff0c;直接重启就好了&#xff0c;如果已经安装过&#xff0c;只需要切换中英文 3.中英文切换 外观与行为&#xf…

单片机库函数-io输出操作

1、需要使用模块 使用库函数做跑马灯&#xff0c;要用到: misc.h misc.c 时钟模块&#xff1a; stm32f10x_rcc.h stm32f10x_rcc.c gpio模块&#xff1a; 头文件:stm32f10x_gpio.h 源文件:stm32f10x_gpio.c 2、库函数 2.1、初始化GPIO void GPIO_Init(GPIO_TypeDef* …

贝叶斯神经网络(Bayesian Neural Network)

最近在研究贝叶斯神经网络,一些概念一直搞不清楚,这里整理一下相关内容,方便以后查阅。 贝叶斯神经网络(Bayesian Neural Network) 贝叶斯神经网络(Bayesian Neural Network)1. BNN 的核心思想2. BNN 的优化目标3. BNN 的结构与特点4. BNN 的训练过程5. BNN 的优缺点6. …

预计5.2.1版本的SharedingSphere Hint指定数据库未生效问题

配置文件展示 shardingsphere:props:sql-show: falsedatasource:names:datacenter1,datacenter2,datacenter3rules:sharding:tables:shape:actual-data-nodes: datacenter$->{1..3}.shape$->{0..7}key-generate-strategy:column: idkey-generator-name: snowflaketable-s…