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

设计模式每日硬核训练 Day 13:桥接模式(Bridge Pattern)完整讲解与实战应用

🔄 回顾 Day 12:装饰器模式小结

在 Day 12 中,我们学习了装饰器模式(Decorator Pattern):

  • 强调在不改变原类结构的前提下,动态为对象增强功能。
  • 通过“包装对象”实现运行时组合,支持功能增强、职责扩展。

今天我们进入结构型设计模式中的另一颗明星——桥接模式(Bridge Pattern)

桥接模式的核心哲学是:将“抽象”与“实现”解耦,使它们可以独立变化。


一、桥接模式的核心动机

在这里插入图片描述

✅ 为什么要桥接?

当我们遇到一个对象,它需要同时支持两个(或多个)维度的变化:

  • 图形:图形类型(圆、矩形) × 渲染方式(OpenGL、Vulkan)
  • 消息:发送渠道(邮件、短信) × 消息类型(普通、加密)

如果使用继承会怎样?

→ CircleOpenGL
→ CircleVulkan
→ RectangleOpenGL
→ RectangleVulkan

会导致类爆炸!每加一个维度,都要组合多个子类。

桥接模式解决的正是:多维变化下,避免子类组合爆炸,将每个维度封装为独立模块,通过桥接连接。


二、结构图(UML)

+---------------------+         +----------------------+
|      Abstraction     |        |    Implementor        |
+---------------------+        +----------------------+
| +operation()         |        | +implOperation()      |
| - impl: Implementor* |        +----------------------+
+---------------------+                   /\/\                              ||/  \                    +----------------------+ 
+--------------------+          | ConcreteImplementorA |
| RefinedAbstraction |          +----------------------+
+--------------------+          | +implOperation()     |+----------------------+

三、角色说明

角色职责说明
Abstraction抽象接口,定义面向客户端的方法
Implementor实现接口,定义基础操作,供 Abstraction 使用
RefinedAbstraction扩展的抽象,具体调用 Implementor 的接口
ConcreteImplementorX实际实现类

四、C++ 实现:图形渲染系统(图形 × 渲染方式)

✅ 实现接口(Implementor)

class IRenderEngine {
public:virtual void renderCircle(float x, float y, float r) = 0;virtual ~IRenderEngine() = default;
};

✅ OpenGL/Vulkan 渲染实现

class OpenGLRenderer : public IRenderEngine {
public:void renderCircle(float x, float y, float r) override {std::cout << "OpenGL 渲染圆: (" << x << ", " << y << ") r=" << r << std::endl;}
};class VulkanRenderer : public IRenderEngine {
public:void renderCircle(float x, float y, float r) override {std::cout << "Vulkan 渲染圆: (" << x << ", " << y << ") r=" << r << std::endl;}
};

✅ 抽象图形类(Abstraction)

class Shape {
protected:IRenderEngine* engine_; // 桥接成员
public:Shape(IRenderEngine* engine) : engine_(engine) {}virtual void draw() = 0;virtual ~Shape() = default;
};

✅ RefinedAbstraction(Circle)

class Circle : public Shape {float x_, y_, r_;
public:Circle(IRenderEngine* engine, float x, float y, float r): Shape(engine), x_(x), y_(y), r_(r) {}void draw() override {engine_->renderCircle(x_, y_, r_);}
};

✅ 使用示例

int main() {OpenGLRenderer opengl;VulkanRenderer vulkan;Circle circle1(&opengl, 10, 10, 5);Circle circle2(&vulkan, 20, 20, 10);circle1.draw();circle2.draw();return 0;
}

输出:

OpenGL 渲染圆: (10, 10) r=5
Vulkan 渲染圆: (20, 20) r=10

五、桥接适合的场景总结

应用场景抽象维度 vs 实现维度
图形渲染框架图形类型(圆/矩形) × 渲染方式(OpenGL/Vulkan/Skia)
消息推送系统消息类型(普通/加密) × 推送方式(短信/邮件/钉钉)
音视频播放引擎媒体类型(音频/视频) × 编解码实现(FFmpeg/GStreamer)
报表生成器报表类型 × 导出格式(PDF/Excel/CSV)

六、与其他模式的对比

模式意图适合场景说明
桥接 Bridge抽象与实现分离,双维度可扩展多维度变化,组合而非继承
适配器接口兼容老系统接入新接口
装饰器功能增强给原对象添加功能(可叠加)
策略算法切换同一流程下支持不同行为切换

七、面试回答模板

“我们在图形模块中使用桥接模式,将图形类型与渲染方式解耦,图形如 Circle、Rectangle 不直接依赖 OpenGL 或 Vulkan,而是通过 IRenderEngine 接口进行桥接。这样我们新增图形类型或渲染引擎时,只需扩展对应层即可,符合开闭原则。”

✅ 建议强调:双维度扩展、组合替代继承、设计层次清晰


八、口诀记忆

“变化不交叉,维度可独立;抽象用桥接,组合不继承。”


九、明日预告:Day 14

组合模式(Composite Pattern):统一叶子节点与整体结构,构建树形层级的一致操作模型。

相关文章:

设计模式每日硬核训练 Day 13:桥接模式(Bridge Pattern)完整讲解与实战应用

&#x1f504; 回顾 Day 12&#xff1a;装饰器模式小结 在 Day 12 中&#xff0c;我们学习了装饰器模式&#xff08;Decorator Pattern&#xff09;&#xff1a; 强调在不改变原类结构的前提下&#xff0c;动态为对象增强功能。通过“包装对象”实现运行时组合&#xff0c;支…...

库洛游戏一面+二面

目录 一面 1. ArrayList和LinkedList的区别&#xff0c;就是我在插入和删除的时候他们在时间复杂度上有什么区别 2. hashmap在java的底层是怎么实现的 3. 红黑树的实现原理 4. 红黑树的特点 5. 为什么红黑树比链表查询速度快 6. 在java中字符串的操作方式有几种 7. Stri…...

前端面试-Vue篇

核心概念 Vue 3的响应式原理与Vue 2有何本质区别&#xff1f;Vue中虚拟DOM的diff算法优化策略有哪些&#xff1f;Vue组件间通信方式有哪些&#xff1f;适用场景分别是什么&#xff1f;Vue的生命周期钩子在Composition API中如何替代&#xff1f;Vue的模板编译过程是怎样的&…...

XSS攻击(反射型、存储型、dom型、PDF、SWF、SVG)

一、XSS攻击是什么 XSS是恶意攻击者往 Web 页面里插入恶意可执行网页脚本代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中 Web 里面的脚本代码会被执行&#xff0c;从而可以达到攻击者盗取用户信息或其他侵犯用户安全隐私的目的。 二、XSS分类 反射型XSS 常见情况是…...

C复习(主要复习)

指针和数组 指针数组是一个数组&#xff0c;数组的每个元素都是指针。它适用于需要存储多个指针的场景&#xff0c;如字符串数组。数组指针是一个指针&#xff0c;指向一个数组。它适用于需要传递整个数组给函数或处理多维数组的场景。 函数指针&#xff1a;函数指针的定义需要…...

Python及C++中的集合

1. Python 中的集合&#xff08;set&#xff09; 1.1 特性 无序性&#xff1a;集合中的元素没有顺序&#xff0c;不能通过索引访问。唯一性&#xff1a;集合中的元素不能重复&#xff0c;如果尝试添加重复的元素&#xff0c;集合会自动忽略。可变性&#xff1a;集合是可变的&…...

Ubuntu24.04搭建ESP8266_RTOS_SDK V3.4开发环境

【本文发布于https://blog.csdn.net/Stack_/article/details/147194686&#xff0c;未经允许不得转载&#xff0c;转载须注明出处】 需要有Linux使用基础&#xff0c;自行准备 1、VM17 Pro &#xff08;自行搜索教程安装&#xff09; 2、ubuntu-24.04-desktop-amd64 &#xff0…...

数据仓库分层存储设计:平衡存储成本与查询效率

数据仓库分层存储不仅是一个技术问题,更是一种艺术:如何在有限的资源下,让数据既能快速响应查询,又能以最低的成本存储? 目录 一、什么是数据仓库分层存储? 二、分层存储的体系架构 1. 数据源层(ODS,Operational Data Store) 2. 数据仓库层(DW,Data Warehouse)…...

matlab求和∑函数方程编程?

matlab求和∑函数方程编程&#xff1f; 一 题目&#xff1a;求下列函数方程式的和 二&#xff1a;代码如下&#xff1a; >> sum_result 0; % 初始化求和变量 for x 1:10 % 设…...

基于Java+MySQL实现的(Web)科研资讯推送系统

科研资讯推送系统 技术选型 核心框架&#xff1a;SpringBoot 数据库层&#xff1a;springdatajpa 安全框架&#xff1a;Shiro 数据库连接池&#xff1a;Druid 缓存&#xff1a;Ehcache 部署 阿里云学生机:ecs.n4.small Tomcat:9.0 JDK:1.8 数据库:MySQL8.0 操作系统:CentOS…...

PHP弱类型hash比较缺陷

目录 0x00 漏洞原因 0x01 利用方法 0x02 [BJDCTF2020]Easy MD5 1 利用md5($password,true)实现SQL注入 PHP md5弱类型比较 数组绕过 0x00 漏洞原因 1、在进行比较的时候&#xff0c;会先将两边的变量类型转化成相同的&#xff0c;再进行比较 2、0e在比较的时候会将其认…...

​asm汇编源代码之-汉字点阵字库显示程序源代码下载​

汉字点阵字库显示程序 源代码下载 文本模式下显示16x16点阵汉字库内容的程序(标准16x16字库需要使用CHGHZK转换过后才能使用本程序正常显示) 本程序需要调用file.asm和string.asm中的子程序,所以连接时需要把它们连接进来,如下 C:\> tlink showhzk file string 调用参…...

Excel 中让表格内容自适应列宽和行高

Excel 中让表格内容自适应列宽和行高 目录 Excel 中让表格内容自适应列宽和行高自适应列宽自适应行高在Excel中让表格内容自适应列宽和行高,可参考以下操作: 自适应列宽 方法一:手动调整 选中需要调整列宽的列(如果是整个表格,可点击表格左上角行号和列号交叉处的三角形全…...

从 Vue 到 React:深入理解 useState 的异步更新

目录 从 Vue 到 React&#xff1a;深入理解 useState 的异步更新与函数式写法1. Vue 的响应式回顾&#xff1a;每次赋值立即生效2. React 的状态更新是异步且批量的原因解析 3. 函数式更新&#xff1a;唯一的正确写法4. 对比 Vue vs React 状态更新5. React useState 的核心源码…...

Java使用ANTLR4对Lua脚本语法校验

文章目录 什么是ANTLR&#xff1f;第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Grammar文件maven配置生成Lexer Parser Listener Visitor代码新建实体类Lua语法遍历器语法错误监听器单元测试 参考 什么是ANTLR&#xff1f; https://www.antlr.org/ ANTLR (ANothe…...

vue3.2 + element-plus 实现跟随input输入框的弹框,弹框里可以分组或tab形式显示选项

效果 基础用法&#xff08;分组选项&#xff09; 高级用法&#xff08;带Tab栏&#xff09; <!-- 弹窗跟随通用组件 SmartSelector.vue --> <!-- 弹窗跟随通用组件 --> <template><div class"smart-selector-container"><el-popove…...

Vue 2.0和3.0笔记

Vue 3 关于组件 今天回顾了下2.0关于组件的内容&#xff0c;3.0定义组件的方式多了一种就是通过单文件组件&#xff08;Single-File Component&#xff09;的方式将Vue的模板&#xff0c;逻辑和样式放到一个文件中&#xff0c;2.0则不同&#xff0c;它是将模板放到一个属性中…...

Windows VsCode Terminal窗口使用Linux命令

背景描述&#xff1a; 平时开发环境以Linux系统为主&#xff0c;有时又需要使用Windows系统下开发环境&#xff0c;为了能像Linux系统那样用Windows VsCode&#xff0c;Terminal命令行是必不可少内容。 注&#xff1a;Windows11 VsCode 1.99.2 下面介绍&#xff0c;如何在V…...

负载均衡的实现方式有哪些?

负载均衡实现方式常见的有: 软件负载均衡、硬件负载均衡、DNS负载均衡 扩展 二层负载均衡&#xff1a;在数据链路层&#xff0c;基于MAC地址进行流量分发&#xff0c;较少见于实际应用中 三层负载均衡&#xff1a;在网络层&#xff0c;基于IP地址来分配流量&#xff0c;例如某…...

Oracle 中的 NOAUDIT CREATE SESSION 命令详解

Oracle 中的 NOAUDIT CREATE SESSION 命令详解 NOAUDIT CREATE SESSION 是 Oracle 数据库中用于取消对用户登录会话审计的命令&#xff0c;它与 AUDIT CREATE SESSION 命令相对应。 一、基本语法 NOAUDIT CREATE SESSION [BY user1 [, user2]... | BY [SESSION | ACCESS]] …...

OutputStreamWriter 终极解析与记忆指南

OutputStreamWriter 终极解析与记忆指南 一、核心本质 OutputStreamWriter 是 Java 提供的字符到字节的桥梁流&#xff0c;属于 Writer 的子类&#xff0c;负责将字符流按指定编码转换为字节流。 注意&#xff1a;OutputStreamWriter也是一个字符流&#xff0c;也是一个转换…...

1022 Digital Library

1022 Digital Library 分数 30 全屏浏览 切换布局 作者 CHEN, Yue 单位 浙江大学 A Digital Library contains millions of books, stored according to their titles, authors, key words of their abstracts, publishers, and published years. Each book is assigned an u…...

LWIP学习笔记

TCP/ip协议结构分层 传输层简记 TCP&#xff1a;可靠性强&#xff0c;有重传机制 UDP&#xff1a;单传机制&#xff0c;不可靠 UDP在ip层分片 TCP在传输层分包 应用层传输层网络层&#xff0c;构成LWIP内核程序&#xff1a; 链路层&#xff1b;由mac内核STM芯片的片上外设…...

Nodejs Express框架

参考&#xff1a;Node.js Express 框架 | 菜鸟教程 第一个 Express 框架实例 接下来我们使用 Express 框架来输出 "Hello World"。 以下实例中我们引入了 express 模块&#xff0c;并在客户端发起请求后&#xff0c;响应 "Hello World" 字符串。 创建 e…...

LeetCode面试热题150中19-22题学习笔记(用Java语言描述)

Day 04 19、最后一个单词的长度 需求&#xff1a;给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 代码表示 public class Q19_1 {p…...

道路运输安全员企业负责人考试内容与范围

道路运输企业主要负责人&#xff08;安全员&#xff09;考证要求 的详细说明&#xff0c;适用于企业法定代表人、分管安全负责人等需取得的 《道路运输企业主要负责人和安全生产管理人员安全考核合格证明》&#xff08;交通运输部要求&#xff09;。 考试内容与范围 1. 法律法…...

Visual Studio Code 开发 树莓派 pico

开发环境 MCU&#xff1a;Pico1&#xff08;无wifi版&#xff09;使用固件&#xff1a;自编译版本开发环境&#xff1a;Windows 10开发工具&#xff1a;Visual Studio Code 1.99.2开发语言&#xff1a;MicroPython & C 插件安装 找到Raspberry Pi Pico并安装开启科学上网…...

Oracle 11G RAC 删除添加节点(一):删除节点

1、查看节点删除前的资源状态 用集群资源查看命令查看一下状态 1 [gridlvmrac1 ~]$crsctl stat res ‐t 2 ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐…...

面试宝典(C++基础)-02

文章目录 1.C++基础1.1 说说new和malloc的区别1.2 说说const和define的区别。1.3 说说C++中函数指针和指针函数的区别1.4 说说const int *a, int const *a, const int a, int *const a, const int *consta分别是什么,有什么特点。1.5 说说使用指针需要注意什么?1.6 说说内联函…...

express框架使用cors包解决跨域问题时,还是存在问题的原因。

express框架使用cors包解决跨域问题时&#xff0c;还是存在问题的原因。 今天我在使用express框架写一个后台管理系统时&#xff0c;发现存在这样的问题&#xff0c;那就是跨域问题&#xff0c;但是我明明是使用了 cors 包解决了跨域问题了。当我调用其他接口的时候&#xff0…...