【C++设计模式】第七篇:桥接模式(Bridge)
注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。
抽象与实现的解耦之道
1. 模式定义与用途
核心思想
- 桥接模式:将抽象部分与实现部分分离,使二者可以独立变化。
- 关键用途:
1.拆分复杂继承树:避免因多维度扩展导致的类爆炸。
2.运行时切换实现:动态组合不同的抽象与实现(如渲染引擎、数据存储方式)。 - 经典场景
1.图形库:形状(抽象)与渲染API(实现)的组合。
2.设备控制:遥控器(抽象)与电器设备(实现)的解耦。
2. 模式结构解析
+---------------------+ +---------------------+
| Abstraction | | Implementor |
+---------------------+ +---------------------+
| - impl: Implementor |<>------->| + operationImpl() |
| + operation(): void | +---------------------+
+---------------------+ ^ ^ | | +-----+-------------+ | | |
+---------------------+ +-------------------+ +-------------------+
| RefinedAbstraction | | ConcreteImplA | | ConcreteImplB |
+---------------------+ +-------------------+ +-------------------+
| + operation() | | + operationImpl() | | + operationImpl() |
+---------------------+ +-------------------+ +-------------------+
角色说明
Abstraction:抽象部分的基类,持有实现部分的引用。-
RefinedAbstraction:扩展抽象功能的具体类。 Implementor:实现部分的接口。ConcreteImplementor:实现部分的具体类。
3. 简单示例:图形渲染引擎桥接
场景:形状与渲染API解耦
// 实现部分:渲染API接口
class RenderAPI {
public: virtual void renderCircle(float x, float y, float radius) = 0; virtual ~RenderAPI() = default;
}; // 抽象部分:形状基类
class Shape {
public: Shape(RenderAPI& api) : api_(api) {} virtual void draw() = 0;
protected: RenderAPI& api_;
}; // 客户端调用
class Circle : public Shape {
public: Circle(RenderAPI& api, float x, float y, float r) : Shape(api), x_(x), y_(y), radius_(r) {} void draw() override { api_.renderCircle(x_, y_, radius_); }
private: float x_, y_, radius_;
};
4. 完整代码:多API与多形状支持
步骤1:实现部分(渲染API)
// 实现接口
class RenderAPI {
public: virtual void renderCircle(float x, float y, float radius) = 0; virtual void renderRect(float x, float y, float w, float h) = 0; virtual ~RenderAPI() = default;
}; // OpenGL实现
class OpenGLAPI : public RenderAPI {
public: void renderCircle(float x, float y, float radius) override { std::cout << "OpenGL渲染圆形:位置(" << x << "," << y << "), 半径" << radius << "\n"; } void renderRect(float x, float y, float w, float h) override { std::cout << "OpenGL渲染矩形:位置(" << x << "," << y << "), 尺寸" << w << "x" << h << "\n"; }
}; // Vulkan实现
class VulkanAPI : public RenderAPI {
public: void renderCircle(float x, float y, float radius) override { std::cout << "Vulkan渲染圆形:位置(" << x << "," << y << "), 半径" << radius << "\n"; } void renderRect(float x, float y, float w, float h) override { std::cout << "Vulkan渲染矩形:位置(" << x << "," << y << "), 尺寸" << w << "x" << h << "\n"; }
};
步骤2:抽象部分(形状与扩展)
// 抽象基类(使用智能指针管理实现)
class Shape {
public: Shape(std::shared_ptr<RenderAPI> api) : api_(api) {} virtual void draw() = 0; virtual ~Shape() = default;
protected: std::shared_ptr<RenderAPI> api_;
}; // 具体形状:圆形
class Circle : public Shape {
public: Circle(std::shared_ptr<RenderAPI> api, float x, float y, float r) : Shape(api), x_(x), y_(y), radius_(r) {} void draw() override { api_->renderCircle(x_, y_, radius_); }
private: float x_, y_, radius_;
}; // 具体形状:矩形
class Rectangle : public Shape {
public: Rectangle(std::shared_ptr<RenderAPI> api, float x, float y, float w, float h) : Shape(api), x_(x), y_(y), width_(w), height_(h) {} void draw() override { api_->renderRect(x_, y_, width_, height_); }
private: float x_, y_, width_, height_;
};
步骤3:客户端动态组合
int main() { // 创建不同渲染API auto opengl = std::make_shared<OpenGLAPI>(); auto vulkan = std::make_shared<VulkanAPI>(); // 动态组合形状与API Circle glCircle(opengl, 10, 10, 5); Circle vkCircle(vulkan, 20, 20, 8); Rectangle glRect(opengl, 5, 5, 10, 6); glCircle.draw(); // 输出:OpenGL渲染圆形:位置(10,10), 半径5 vkCircle.draw(); // 输出:Vulkan渲染圆形:位置(20,20), 半径8 glRect.draw(); // 输出:OpenGL渲染矩形:位置(5,5), 尺寸10x6
}
5. 优缺点分析
| 优点 | 缺点 |
|---|---|
| 分离抽象与实现,减少继承层次 | 增加类的数量 |
| 支持运行时动态切换实现 | 需要设计合理的抽象接口 |
| 提升跨平台、跨模块的扩展性 | 对简单场景可能过度设计 |
6. 调试与优化策略
调试技巧(VS2022)
- 验证桥接连接:
在draw()方法中设置断点,检查api_指针是否指向正确的实现对象。 - 多态类型识别:
使用typeid(*api_).name()输出实际类型(需启用RTTI)。
性能优化
- 缓存实现对象:
对频繁使用的实现(如OpenGLAPI)使用单例或对象池。 - 移动语义优化:
// 使用移动语义传递渲染API所有权
Shape(std::shared_ptr<RenderAPI>&& api) : api_(std::move(api)) {}
相关文章:
【C++设计模式】第七篇:桥接模式(Bridge)
注意:复现代码时,确保 VS2022 使用 C17/20 标准以支持现代特性。 抽象与实现的解耦之道 1. 模式定义与用途 核心思想 桥接模式:将抽象部分与实现部分分离,使二者可以独立变化。关键用途: 1.拆分复杂继承…...
Html常用代码
Html常用代码 文章目录 Html常用代码1-常用的Html代码1-Html模板 2-快速部署Live-Server1-Windows系统步骤 1:安装 Node.js步骤 2:安装 live - server步骤 3:使用 live - server 运行本地项目 2-Mac系统步骤 1:安装 Node.js步骤 2…...
c++中的一些控制符
控制符在<iomanip>头文件里 一、设置显示小数精度 :setprecision() float A3.1234; 默认有效位为6位,steprecision(3)→设置有效位为3位 【3.12】 可以与fixed搭配用,cout<<fixed<<setprecision(3)<&l…...
Go语言里面的堆跟栈 + new 和 make + 内存逃逸 + 闭包
在 Go 语言中,堆(Heap)和栈(Stack)是内存管理中的两个重要概念,它们在内存分配、数据存储和使用场景等方面存在明显差异。 栈(Stack) 栈是一种具有后进先出(LIFO&#…...
蓝桥备赛(11)- 数据结构、算法与STL
一、数据结构 1.1 什么是数据结构? 在计算机科学中,数据结构是一种 数据组织、管理和存储的格式。它是相互之间存在一种 或多种特定关系的数据元素的集合。 ---> 通俗点,数据结构就是数据的组织形式 , 研究数据是用什么方…...
react 19版中路由react-router-dom v7版的使用
路由的安装: npm install react-router-dom在src目录下建一个router文件夹 在router文件夹里面建一个index.tsx index.tsx内容: import React from react; import {BrowserRouter as Router,Routes,Route,Link } from react-router-dom; import ManuLi…...
WPS工具栏添加Mathtype加载项
问题描述: 分别安装好WPS和MathType之后,WPS工具栏没直接显示MathType工具,或者是前期使用正常,由于WPS更新之后MathType工具消失,如下图 解决办法 将文件“MathType Commands 2016.dotm”和“MathPage.wll”从Matht…...
Tauri+React+Ant Design跨平台开发环境搭建指南
TauriReactAnt Design跨平台开发环境搭建指南 一、环境配置与工具链搭建 1.1 基础环境准备 必备组件: Rust工具链(v1.77): curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh Node.js LTS(v20.11.1&a…...
PDF转JPG(并去除多余的白边)
首先,手动下载一个软件(poppler for Windows),下载地址:https://github.com/oschwartz10612/poppler-windows/releases/tag/v24.08.0-0 否则会出现以下错误: PDFInfoNotInstalledError: Unable to get pag…...
std::string的模拟实现
目录 string的构造函数 无参数的构造函数 根据字符串初始化 用n个ch字符初始化 用一个字符串的前n个初始化 拷贝构造 用另一个string对象的pos位置向后len的长度初始化 [ ]解引用重载 迭代器的实现 非const版本 const版本 扩容reserve和resize reserve resize p…...
wordpress自定the_category的输出结构
通过WordPress的过滤器the_category来自定义输出内容。方法很简单,但是很实用。以下是一个示例代码: function custom_the_category($thelist, $separator , $parents ) {// 获取当前文章的所有分类$categories get_the_category();if (empty($categ…...
doris: Oracle
Apache Doris JDBC Catalog 支持通过标准 JDBC 接口连接 Oracle 数据库。本文档介绍如何配置 Oracle 数据库连接。 使用须知 要连接到 Oracle 数据库,您需要 Oracle 19c, 18c, 12c, 11g 或 10g。 Oracle 数据库的 JDBC 驱动程序,您可以从 Maven 仓库…...
mysql中什么机制保证宕机数据恢复
MySQL 通过多种机制来保证在宕机或意外崩溃时数据的完整性和可恢复性。这些机制主要包括 事务日志、崩溃恢复 和 数据持久化 等。以下是 MySQL 中保证数据恢复的核心机制: 1. 事务日志(Transaction Log) 事务日志是 MySQL 实现数据恢复的核心机制之一,主要包括 Redo Log(…...
前端面试技术性场景题
87.场景面试之大数运算:超过js中number最大值的数怎么处理 在 JavaScript 中,Number.MAX_SAFE_INTEGER(即 2^53 - 1,即 9007199254740991)是能被安全表示的最大整数。超过此值时,普通的 Number 类型会出现…...
解决CentOS 8.5被恶意扫描的问题
CentOS 8 官方仓库已停止维护(EOL),导致一些常用依赖包如fail2ban 无法正常安装。 完整解决方案: 一、问题根源 CentOS 8 官方仓库已停更:2021 年底 CentOS 8 停止维护,默认仓库的包可能无法满足依赖关系。EPEL 仓库兼容性:EPEL 仓库可能未适配 CentOS 8.5 的旧版本依赖…...
探秘基带算法:从原理到5G时代的通信变革【四】Polar 编解码(二)
文章目录 2.3.3 极化编码巴氏参数与信道可靠性比特混合生成矩阵编码举例 2.3.4 极化译码最小单元译码串行抵消译码(SC译码)算法SCL译码算法 2.3.5 总结**Polar 码的优势****Polar 码的主要问题****Polar 码的应用前景** 2.3.6 **参考文档** 本博客为系列…...
机器学习准备工作
机器学习准备工作 机器学习概述常见算法动手实践 深度学习基础框架应用领域 数学基础线性代数概率论和统计学微积分 编程基础Python基础数据处理工具 项目实战入门1. Scikit-learn 示例项目2. TensorFlow/Keras 入门项目3. Kaggle 入门竞赛 进阶1. PyTorch 官方教程2. MMDetect…...
汽车智能钥匙中PKE低频天线的作用
PKE(Passive Keyless Entry)即被动式无钥匙进入系统,汽车智能钥匙中PKE低频天线在现代汽车的智能功能和安全保障方面发挥着关键作用,以下是其具体作用: 信号交互与身份认证 低频信号接收:当车主靠近车辆时…...
Codepen和tailwindcss 进行UI布局展示
html <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>设备管理仪表盘</title><script src"https://cdn.tailw…...
准备好了数据集之后,如何在ubuntu22.04上训练一个yolov8模型。
在Ubuntu 22.04上训练YOLOv8模型的步骤如下: 1. 安装依赖 首先,确保系统已安装Python和必要的库。 sudo apt update sudo apt install python3-pip python3-venv2. 创建虚拟环境 创建并激活虚拟环境: python3 -m venv yolov8_env source…...
集合框架、Collection、list、ArrayList、Set、HashSet和LinkedHashSet、判断两个对象是否相等
DAY7.1 Java核心基础 集合框架 Java 中很重要的一个知识点,实际开发中使用的频录较高,Java 程序中必备的模块 集合就是长度可以改变,可以保存任意数据类型的动态数组 最上层是一组接口,接下来是接口的实现类,第三层…...
宝塔 Linux 计划任务中添加运行项目网站PHP任务-定时任务
一、指定php版运行, cd /www/wwwroot/www.xxx.com/ && /www/server/php/56/bin/php think timedtasks start >> /tmp/timedtasks.log 2>&1 二、不指定php版 cd /www/wwwroot/www.xxx.com/ && php think timedtasks start >> …...
JDK ZOOKEEPER KAFKA安装
JDK17下载安装 mkdir -p /usr/local/develop cd /usr/local/develop 将下载的包上传服务器指定路径 解压文件 tar -zxvf jdk-17.0.14_linux-x64_bin.tar.gz -C /usr/local/develop/ 修改文件夹名 mv /usr/local/develop/jdk-17.0.14 /usr/local/develop/java17 配置环境变量…...
c++雅兰亭库 (yalantinglibs) 介绍及使用(序列化、json和结构体转换、协程
c雅兰亭库 (yalantinglibs) 介绍及使用(序列化、json和结构体转换、协程)-CSDN博客 雅兰亭库(yalantinglibs)介绍 雅兰亭库,名字很优雅,也很强大。它是阿里开源的一个现代C基础工具库的集合, 现在包括 struct_pack, struct_json, struct_xml, struct_yam…...
深度融合,智领未来丨zAIoT 全面集成 DeepSeek,助力企业迎接数据智能新时代
前言 Introduction 在数字化浪潮汹涌澎湃的当下,数据智能成为企业破局与创新的关键驱动力。zAIoT 作为云和恩墨面向 AIData 时代推出的数据智能平台软件,凭借其全面且强大的“采存算用”一体化功能体系,正在为航空航天、工业制造等领域和态势…...
类和对象—多态—案例2—制作饮品
案例描述: 制作饮品的大致流程为:煮水-冲泡-倒入杯中-加入辅料 利用多态技术实现本案例,提供抽象制作产品基类,提供子类制作咖啡和茶叶 思路解析: 1. 定义抽象基类 - 创建 AbstractDrinking 抽象类,该类…...
VSCode 配置优化指南:打造高效的 uni-app、Vue2/3、JS/TS 开发环境
VSCode 配置优化指南,适用于 uni-app、Vue2、Vue3、JavaScript、TypeScript 开发,包括插件推荐、设置优化、代码片段、调试配置等,确保你的开发体验更加流畅高效。 1. 安装 VSCode 如果你还未安装 VSCode,可前往 VSCode 官网 下载最新版并安装。 2. 安装推荐插件 (1) Vue…...
低代码平台的后端架构设计与核心技术解析
引言:低代码如何颠覆传统后端开发? 在传统开发模式下,一个简单用户管理系统的后端开发需要: 3天数据库设计5天REST API开发2天权限模块对接50个易出错的代码文件 而现代低代码平台通过可视化建模自动化生成,可将开发…...
Redis中多大的Key算热key,该如何解决
在 Redis 中,“热key” 是指频繁访问的 Redis 键。这些键通常会导致 Redis 服务器的性能下降,甚至可能导致 Redis 服务不可用。热key 的大小是相对的,通常来说,以下几个因素可能导致一个 Redis 键成为热key: 访问频率…...
机器学习数学基础:43.外生变量与内生变量
外生变量与内生变量:模型中的因果角色 在因果模型(像结构方程模型、回归分析这类)里,外生变量和内生变量是用来区分变量来源和相互关系的重要概念。下面从定义、实例、差异以及应用场景四个方面来详细介绍: 一、定义…...
