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

C++设计模式:桥接模式(Bridge)

什么是桥接模式?

桥接模式(Bridge Pattern)是一个用来解耦的设计模式,它将抽象层实现层分离开,让它们可以独立变化。用最简单的话来说,就是让你能够改变抽象的功能具体的实现,而不需要修改对方的代码。

举个例子,想象你在做一个图形绘制的程序,你有很多图形(比如圆形、方形),而且每种图形可能有不同的绘制方式(比如屏幕绘制、打印机绘制)。如果你把所有的图形和绘制方式都写在一起,每次你增加一种新的绘制方式或新图形时,你都要修改大量的代码,这样就会让系统变得很复杂。

桥接模式的思路是:把**图形(抽象)绘制方式(实现)**分开,每一部分都可以独立变化,互不干扰。这样一来,增加新的图形或者新的绘制方式时,就不需要修改现有的代码,只需要扩展新的类即可。

桥接模式的结构

桥接模式有两个重要部分:

  1. 抽象部分(比如图形的类型,如圆形、方形等)
  2. 实现部分(比如具体的绘制方式,如屏幕绘制、打印绘制等)

这两个部分通过“桥”连接起来,形成了一个灵活可扩展的结构。下面的代码结构就能帮助你理解这一点。

桥接模式的代码示例

假设我们要实现一个图形绘制的程序,支持不同的图形(圆形、方形)和不同的绘制方式(屏幕绘制、打印机绘制)。我们来看看怎么用桥接模式来实现。

#include <iostream>
#include <string>// 绘图接口(实现类接口)
class DrawingAPI {
public:virtual void drawCircle(double x, double y, double radius) = 0;virtual ~DrawingAPI() = default;
};// 具体实现:屏幕绘制
class ScreenDrawingAPI : public DrawingAPI {
public:void drawCircle(double x, double y, double radius) override {std::cout << "在屏幕上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;}
};// 具体实现:打印机绘制
class PrinterDrawingAPI : public DrawingAPI {
public:void drawCircle(double x, double y, double radius) override {std::cout << "在打印机上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;}
};// 图形类(抽象类)
class Shape {
protected:DrawingAPI* drawingAPI;  // 这里持有一个指向绘图实现类的指针public:Shape(DrawingAPI* api) : drawingAPI(api) {}  // 通过构造函数注入具体实现类virtual void draw() = 0;  // 绘制图形的接口virtual void resize(double factor) = 0;  // 调整图形大小virtual ~Shape() = default;
};// 扩展的具体图形类:圆形
class Circle : public Shape {
private:double x, y, radius;  // 圆形的坐标和半径public:Circle(double x, double y, double radius, DrawingAPI* api) : Shape(api), x(x), y(y), radius(radius) {}void draw() override {drawingAPI->drawCircle(x, y, radius);  // 将绘制任务委托给具体实现}void resize(double factor) override {radius *= factor;  // 调整圆形的半径}
};int main() {ScreenDrawingAPI screenAPI;  // 创建屏幕绘制实现PrinterDrawingAPI printerAPI;  // 创建打印机绘制实现// 创建圆形对象,使用不同的绘制方式Circle circle1(1, 2, 3, &screenAPI);  // 在屏幕上绘制Circle circle2(5, 6, 4, &printerAPI);  // 在打印机上绘制circle1.draw();  // 屏幕绘制圆形circle2.draw();  // 打印机绘制圆形circle1.resize(2.0);  // 改变圆形大小circle1.draw();  // 再次绘制,使用屏幕绘制return 0;
}

代码讲解

让我们一步步来解读这段代码,看看桥接模式是如何工作的。

1. 绘图接口(DrawingAPI
class DrawingAPI {
public:virtual void drawCircle(double x, double y, double radius) = 0;virtual ~DrawingAPI() = default;
};

这个类定义了一个绘制圆形的方法 drawCircle,它只是一个接口,并不做具体的绘制工作。任何具体的绘制方式(比如屏幕绘制、打印机绘制)都需要实现这个接口。

2. 具体的绘图实现(ScreenDrawingAPIPrinterDrawingAPI
class ScreenDrawingAPI : public DrawingAPI {
public:void drawCircle(double x, double y, double radius) override {std::cout << "在屏幕上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;}
};class PrinterDrawingAPI : public DrawingAPI {
public:void drawCircle(double x, double y, double radius) override {std::cout << "在打印机上绘制圆形,位置: (" << x << ", " << y << "), 半径: " << radius << std::endl;}
};

这两个类分别实现了 DrawingAPI 接口,提供了不同的绘制方式。ScreenDrawingAPI 在屏幕上绘制圆形,PrinterDrawingAPI 在打印机上绘制圆形。

3. 抽象类(Shape
class Shape {
protected:DrawingAPI* drawingAPI;  // 持有一个绘图实现类的指针public:Shape(DrawingAPI* api) : drawingAPI(api) {}  // 通过构造函数注入具体的绘图实现virtual void draw() = 0;  // 绘制图形的接口virtual void resize(double factor) = 0;  // 调整图形大小
};

Shape 是一个抽象类,它定义了所有图形的共同接口:draw()resize()。关键是它持有一个 DrawingAPI 的指针,这样它可以将具体的绘制任务委托给实现类。

4. 具体图形类(Circle
class Circle : public Shape {
private:double x, y, radius;  // 圆形的坐标和半径public:Circle(double x, double y, double radius, DrawingAPI* api) : Shape(api), x(x), y(y), radius(radius) {}void draw() override {drawingAPI->drawCircle(x, y, radius);  // 调用具体绘图实现的drawCircle方法}void resize(double factor) override {radius *= factor;  // 改变圆形的半径}
};

Circle 类继承自 Shape,并实现了 draw()resize() 方法。它通过 drawingAPI 指针来调用具体的绘制方法,实现了与绘制方式的解耦。

5. 客户端代码

main 函数中,我们创建了两个 Circle 对象,分别使用了 ScreenDrawingAPIPrinterDrawingAPI 作为绘制实现。通过调用 circle1.draw()circle2.draw(),我们可以看到两个不同的绘制方式。

int main() {ScreenDrawingAPI screenAPI;  // 屏幕绘制实现PrinterDrawingAPI printerAPI;  // 打印机绘制实现// 创建两个圆形对象,分别使用不同的绘制方式Circle circle1(1, 2, 3, &screenAPI);Circle circle2(5, 6, 4, &printerAPI);circle1.draw();  // 屏幕绘制圆形circle2.draw();  // 打印机绘制圆形circle1.resize(2.0);  // 改变圆形大小circle1.draw();  // 再次绘制,使用屏幕绘制return 0;
}

总结

桥接模式的主要优点就是解耦

。我们把抽象部分(如图形类型)和实现部分(如绘制方式)分开,避免了两者之间的紧耦合。这样我们可以很方便地扩展新的图形类型或新的绘制方式,而不需要修改现有的代码。

比如,如果你以后需要支持新的绘制方式(比如在Web上绘制),你只需要实现一个新的 DrawingAPI 类,不用改动任何图形类;同样,如果你需要增加新的图形类型(比如矩形),只需要扩展 Shape 类,不需要改动任何绘制实现。

桥接模式适用于需要将抽象和实现分离,并且它们可能会独立变化的场景。

本文由mdnice多平台发布

相关文章:

C++设计模式:桥接模式(Bridge)

什么是桥接模式&#xff1f; 桥接模式&#xff08;Bridge Pattern&#xff09;是一个用来解耦的设计模式&#xff0c;它将抽象层和实现层分离开&#xff0c;让它们可以独立变化。用最简单的话来说&#xff0c;就是让你能够改变抽象的功能和具体的实现&#xff0c;而不需要修改…...

spark3.x之后时间格式数据偶发报错org.apache.spark.SparkUpgradeException

3.x之后如果你去处理2.x生成的时间字符串数据&#xff0c;很容易遇到一个问题 Error operating ExecuteStatement: org.apache.spark.SparkUpgradeException: You may get a different result due to the upgrading of Spark 3.0: Fail to parse 20200725__cb90fcc3_8006_46…...

spring boot框架漏洞复现

spring - java开源框架有五种 Spring MVC、SpringBoot、SpringFramework、SpringSecurity、SpringCloud spring boot版本 版本1: 直接就在根下 / 版本2:根下的必须目录 /actuator/ 端口:9093 spring boot搭建 1:直接下载源码打包 2:运行编译好的jar包:actuator-testb…...

下载安装Android Studio

&#xff08;一&#xff09;Android Studio下载地址 https://developer.android.google.cn/studio 滑动到 点击下载文档 打开新网页 切换到english ![](https://i-blog.csdnimg.cn/direct/b7052b434f9d4418b9d56c66cdd59fae.png 等待一会&#xff0c;出现 点同意后&#xff0…...

三、计算机视觉_08YOLO目标检测

0、前言 YOLO作为目前CV领域的扛把子&#xff0c;分类、检测等任务样样精通&#xff0c;本文将基于两个小案例&#xff0c;用YOLO做检测任务&#xff0c;看看效果如何 1、对图片内容做检测 假设我有一张名为picture.jpeg的图片&#xff0c;其内容如下 我将图片和代码放到了同…...

uniapp关闭sourceMap的生成,提高编译、生产打包速度

警告信息&#xff1a;[警告⚠] packageF\components\mpvue-echarts\echarts.min.js 文件体积超过 500KB&#xff0c;已跳过压缩以及 ES6 转 ES5 的处理&#xff0c;手机端使用过大的js库影响性能。 遇到问题&#xff1a;由于微信小程序引入了mpvue-echarts\echarts.min.js&…...

uniapp首页样式,实现菜单导航结构

实现菜单导航结构 1.导入字体图标库需要的文件 2.修改引用路径iconfont.css 3.导入到App.vue中 <style>import url(./static/font/iconfont.css); </style>导航区域代码 VUE代码 <template><view class"home"><!-- 导航区域 --><…...

uniapp-vue2引用了vue-inset-loader插件编译小程序报错

报错信息 Error: Vue packages version mismatch: - vue3.2.45 (D:\qjy-myApp\admin-app\node_modules\vue\index.js) - vue-template-compiler2.7.16 (D:\qjy-myApp\admin-app\node_modules\vue-template-compiler\package.json) This may cause things to work incorrectly.…...

Git命令大全(超详细)

Git 是一个分布式版本控制系统&#xff0c;用于跟踪计算机文件的更改&#xff0c;并协调多个用户之间的工作。下面是一份较为详细的 Git 命令大全&#xff0c;涵盖了从初始化仓库到日常使用中常见的操作。 1. 初始化与配置 设置用户信息: git config --global user.name &quo…...

【机器学习】机器学习学习笔记 - 监督学习 - 逻辑回归分类朴素贝叶斯分类支持向量机 SVM (可分类、可回归) - 04

逻辑回归分类 import numpy as np from sklearn import linear_modelX np.array([[4, 7], [3.5, 8], [3.1, 6.2], [0.5, 1], [1, 2], [1.2, 1.9], [6, 2], [5.7, 1.5], [5.4, 2.2]]) y np.array([0, 0, 0, 1, 1, 1, 2, 2, 2])# 逻辑回归分类器 # solver&#xff1a;求解器&a…...

常见的数据结构---数组、链表、栈的深入剖析

目录 一、数组&#xff08;Array&#xff09; 二、链表&#xff08;Linked List&#xff09; 三、栈&#xff08;Stack&#xff09; 四、总结 数据结构是算法的基石&#xff0c;是程序设计的核心基础。不同的数据结构适用于不同的场景和需求&#xff0c;选择合适的数据结构能…...

前端开发:构建高质量用户体验的全方位指南(含实际案例与示例)

前端开发&#xff1a;构建高质量用户体验的全方位指南&#xff08;含实际案例与示例&#xff09; 在当今数字化时代&#xff0c;前端技术不仅是网页和应用的门面&#xff0c;更是连接用户与数字世界的桥梁。一个高质量的前端开发项目不仅能够提升用户体验&#xff08;UX&#…...

Istio_05_Istio架构

Istio_05_Istio架构 ArchitectureControl PlanePilotCitadelGalley Data PlaneSidecarIstio-proxyPilot-agentMetadta Exchange Ambient Architecture 如: Istio的架构(控制面、数据面) Gateway: Istio数据面的出/入口网关 Gateway分为: Ingress-gateway、Egress-gateway外部访…...

MongoDB集群分片安装部署手册

文章目录 一、集群规划1.1 集群安装规划1.2 端口规划1.3 目录创建 二、mongodb安装&#xff08;三台均需要操作&#xff09;2.1 下载、解压2.2 配置环境变量 三、mongodb组件配置3.1 配置config server的副本集3.1.1 config配置文件3.1.2 config server启动3.1.3 初始化config …...

摄像头测距原理

以下是测距摄像头分类的 Markdown 格式输出&#xff0c;方便直接复制使用&#xff1a; 测距摄像头分类 1. 立体视觉&#xff08;Stereo Vision&#xff09;摄像头 原理&#xff1a;模仿人眼成像&#xff0c;利用两台摄像头获取不同视角的图像&#xff0c;通过视差计算场景深…...

基于centos7.9使用shell脚本部署k8s1.25平台

k8s 环境初始化安装Harbor安装k8s安装istio和kubevirt 使用脚本部署k8s1.25版本平台&#xff0c;网络插件使用flannel &#xff0c;容器运行时ctr&#xff0c;部署包括harbor仓库&#xff0c;服务网格、kubevirt服务等 使用的centos7.9资源配置如下&#xff1a; 主机IP资源ma…...

11.29周五F34-Day10打卡

文章目录 1. 问问他能不能来。解析答案:【解析答案分析】【对比分析】【拓展内容】2. 问题是他能不能做。解析答案:【解析答案分析】3. 问题是我们能否联系得上她。(什么关系?动作 or 描述?)解析答案:【解析答案分析】【对比分析】4. 我们在讨论是否要开一个会。解析答案:…...

龙迅#LT8612UX适用于HDMI 转 HDMIVGA应用领域,分辨率高达4K60HZ,内置程序,方便调试!

1. 描述 LT8612UX 是一款 HDMI 转 HDMI&VGA 转换器&#xff0c;可将 HDMI2.0 数据流转换为 HDMI2.0 信号和模拟 RGB 信号。它还输出 8 通道 I2S 和 SPDIF 信号&#xff0c;可实现高质量的 7.1 通道音频。 LT8612UX 使用最新的 ClearEdge 技术&#xff0c;除了原始的 HDMI…...

C#学写了一个程序记录日志的方法(Log类)

1.错误和警告信息单独生产文本进行记录&#xff1b; 2.日志到一定内存阈值可以打包压缩&#xff0c;单独存储起来&#xff0c;修改字段MaxLogFileSizeForCompress的值即可&#xff1b; 3.Log类调用举例&#xff1a;Log.Txt(JB.信息,“日志记录内容”,"通道1"); usi…...

时间相关转换

Timestamp(date,type) { const zeroDate = new Date(date); if(type === startTime){ zeroDate.setHours(0, 0, 0, 0); } if(type === endTime){ zeroDate.setHours(23, 59, 59, 999); } return zeroDate.getTime(); }, //**时间戳转…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

2025-05-08-deepseek本地化部署

title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek&#xff1a;小白也能轻松搞定&#xff01; 如何给本地部署的 DeepSeek 投喂数据&#xff0c;让他更懂你 [实验目的]&#xff1a;理解系统架构与原…...

k8s从入门到放弃之Pod的容器探针检测

k8s从入门到放弃之Pod的容器探针检测 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;容器探测是指kubelet对容器执行定期诊断的过程&#xff0c;以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...

C++11 constexpr和字面类型:从入门到精通

文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…...

鸿蒙APP测试实战:从HDC命令到专项测试

普通APP的测试与鸿蒙APP的测试有一些共同的特征&#xff0c;但是也有一些区别&#xff0c;其中共同特征是&#xff0c;它们都可以通过cmd的命令提示符工具来进行app的性能测试。 其中区别主要是&#xff0c;对于稳定性测试的命令的区别&#xff0c;性能指标获取方式的命令的区…...

stm32—ADC和DAC

ADC和DAC 在嵌入式系统中&#xff0c;微控制器经常需要与现实世界的模拟信号进行交互。STM32微控制器内置了模拟数字转换器&#xff08;ADC&#xff09;和数字模拟转换器&#xff08;DAC&#xff09;&#xff0c;它们是实现这种交互的关键模块。 1. 模拟数字转换器&#xff08…...