23种设计模式-结构型模式-桥接器
文章目录
- 简介
- 问题
- 解决方案
- 示例
- 总结
简介
桥接器是一种结构型设计模式,可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构,从而能在开发时分别使用。
问题
假如你有一个几何形状Shape类,它有两个子类:圆形Circle和方形Square。现在你想对类层次结构进行扩展,让它包含颜色属性,所以你打算创建 红色Red和 蓝色Blue的形状子类。但是,由于你已有两个子类,所以总共需要创建四个类才能覆盖所有组合,比如蓝色圆形BlueCircle和红色方形RedSquare。

在层次结构里新增形状和颜色都会导致代码复杂程度指数增长。比如添加三角形状,你需要新增两个子类,也就是每种颜色一个;此后新增一种新颜色需要新增三个子类,即每种形状一个。代码就越来越复杂。
解决方案
问题的根本原因是我们试图在两个独立的维度(形状与颜色)上扩展形状类。我们在使用类继承时经常遇到这样的问题。
桥接模式通过把继承改为组合的方式来解决这个问题。具体来说,就是抽取其中一个维度并让他成为独立的类层次,这样就可以在原来的类中引用这个新层次的对象,从而让一个类不需要拥有所有的状态和行为。

根据这种方法,我们可以把颜色相关的代码抽取到拥有红色和蓝色两个子类的颜色父类中,然后在形状类里添加一个指向某一颜色对象的引用成员变量。这个时候,形状类就可以把所有跟颜色相关的工作委派给引入的颜色对象。这样的引用就成为了形状和颜色之间的桥梁。在这之后,新增颜色都不再需要修改形状的类层次,反过来也一样。
示例
以上示例还比较简单,我们来看一个更复杂的示例,以便演示了桥接模式,看看它怎么拆分程序里同时管理设备和遥控器的复杂代码。设备Device类作为实现部分,而遥控器Remote类则作为抽象部分。

/* 实现层级:设备接口规范 */
public interface Device {// 状态检测基础方法boolean isEnabled();void enable(); // Device接口定义void disable();// 媒体控制方法int getVolume();void setVolume(int percent);int getChannel();void setChannel(int channel);
}/* 具体设备实现 */
class Tv implements Device { // TV实现private boolean on = false;private int volume = 50;private int channel = 1;public boolean isEnabled() { return on; }public void enable() { on = true; } // TV特有启动过程public void disable() { on = false; }public int getVolume() { return volume; }public void setVolume(int percent) { volume = Math.max(0, Math.min(100, percent)); }public int getChannel() { return channel; }public void setChannel(int ch) { channel = Math.max(1, ch); }
}class Radio implements Device { // Radio实现private boolean active = false;private int level = 30;public boolean isEnabled() { return active; }public void enable() { active = true; }public void disable() { active = false; }public int getVolume() { return level; }public void setVolume(int percent) {level = (percent > 100) ? 100 : Math.max(0, percent);}public int getChannel() { return 0; } // 收音机无频道public void setChannel(int ch) {} // 空实现
}/* 抽象层级:遥控器抽象 */
abstract class RemoteControl {// 持有实现层对象的引用(关键结构)protected Device device; public RemoteControl(Device device) {this.device = device;}// 电源切换核心逻辑public void togglePower() {if (device.isEnabled()) {device.disable();} else {device.enable();}}public void volumeUp() {device.setVolume(device.getVolume() + 10);}public void volumeDown() {device.setVolume(device.getVolume() - 10);}public void channelUp() {device.setChannel(device.getChannel() + 1);}public void channelDown() {device.setChannel(device.getChannel() - 1);}
}/* 扩展抽象:高级遥控器(扩展功能) */
class AdvancedRemoteControl extends RemoteControl {public AdvancedRemoteControl(Device device) {super(device);}public void mute() { // 新增静音功能device.setVolume(0); // 通过接口操作设备}
}// 客户端使用示例
public class Client {public static void main(String[] args) {Device tv = new Tv();RemoteControl basicRemote = new RemoteControl(tv);basicRemote.togglePower(); // 开启电视Device radio = new Radio();AdvancedRemoteControl advancedRemote = new AdvancedRemoteControl(radio);advancedRemote.mute(); // 设置静音}
}
总结

- 抽象部分(Abstraction):提供高层控制逻辑,依赖完成底层实际工作的具体实现对象。
- 实现部分(Implementation):为所有具体实现声明通用接口。抽象部分仅能通过在这里声明的方法和实现对象交互。抽象部分可以列出和实现部分一样的方法,但是抽象部分通常声明一些复杂的行为,这些行为依赖于多种由实现部分声明的操作。
- 具体实现(Concrete Implementations)中包括特定平台的代码。
- 精确抽象(Refined Abstraction)提供控制逻辑的变体。和它的父类一样,它们通过通用实现接口与不同的实现进行交互。
- 通常情况下,客户端(Client)仅关心如何与抽象部分合作。但是,客户端需要把抽象对象和一个实现对象连接起来。
相关文章:
23种设计模式-结构型模式-桥接器
文章目录 简介问题解决方案示例总结 简介 桥接器是一种结构型设计模式,可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构,从而能在开发时分别使用。 问题 假如你有一个几何形状Shape类,它有两个子类:圆形C…...
K8S学习之基础五十八:部署nexus服务
部署nexus服务 Nexus服务器是一个代码包管理的服务器,可以理解 Nexus 服务器是一个巨大的 Library 仓库。Nexus 可以支持管理的工具包括 Maven , npm 等,对于 JAVA 开发来说,只要用到 Maven 管理就可以了。Nexus服务器作用&#x…...
Docker Desktop 界面功能介绍
Docker Desktop 界面功能介绍 左侧导航栏 Containers(容器): 用于管理容器,包括查看运行中或已停止的容器,检查容器状态、日志,执行容器内命令,启动、停止、删除容器等操作。Images(镜像): 管理本地 Docker 镜像,可查看镜像列表、从 Docker Hub 拉取新镜像、删除镜…...
C++ set map
1.set和map是什么 set和map是 C STL 提供的容器,用于高效的查找数据,底层采用红黑树实现,其中set是Key模型,map是Key-Value模型 set和map的基本使用较为简单,这里不再叙述,直接进入实现环节 2.set和map的…...
Spring AI Alibaba 对话记忆使用
一、对话记忆 (ChatMemory)简介 1、对话记忆介绍 ”大模型的对话记忆”这一概念,根植于人工智能与自然语言处理领域,特别是针对具有深度学习能力的大型语言模型而言,它指的是模型在与用户进行交互式对话过程中,能够追踪、理解并利…...
Ubuntu24.04 离线安装 MySQL8.0.41
一、环境准备 1.1 官方下载MySQL8.0.41 完整包 1.2 上传包 & 解压 上传包名称是:mysql-server_8.0.41-1ubuntu24.04_amd64.deb-bundle.tar # 切换到上传目录 cd /home/MySQL8 # 解压: tar -xvf mysql-server_8.0.41-1ubuntu24.04_amd64.deb-bundl…...
SOME/IP-SD -- 协议英文原文讲解10
前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 5.1.5 Non…...
Ubuntu上给AndroidStudio创建桌面图标
最近使用了Ubuntu开发了,默认的android studio没有桌面图标,还是很不方便,每次都要cd到bin目录启动studio.sh。 步骤1:cd /usr/share/applications linux系统里面,所有的应用启动入口都在 /usr/share/applications …...
简单视图函数
视图函数 文章目录 视图函数[toc]一、什么是视图函数二、简单视图函数三、返回错误视图 一、什么是视图函数 所谓视图函数(简称视图),本质上就是一个Python函数,用于接收Web请求并且返回Web响应。Web响应可以包含很多类型&#x…...
Flutter 2025生态全景:从跨端到嵌入式开发的新机遇
一、技术演进:从"一次编写多端运行"到"全场景覆盖" 1.1 渲染引擎革命:Impeller 2.0的性能突破 // 启用Impeller的配置示例(android/app/build.gradle) def enableImpeller true android {defaultConfig {…...
【sylar-webserver】7 定时器模块
文章目录 设计知识点 设计 #mermaid-svg-RbjvgaHrVWa5mA9X {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-RbjvgaHrVWa5mA9X .error-icon{fill:#552222;}#mermaid-svg-RbjvgaHrVWa5mA9X .error-text{fill:#552222;s…...
蓝桥杯备考----》完全背包模板
其实这个完全背包的步骤和01背包也是差不多滴,不过他有一些优化是我们必须要说一说的 老样子,我们先定义一下状态表示 step1: f[i][j]表示从1到i个物品里选出体积不超过j的最大价值 step2:状态转移方程 写成一行就是 我们再写一下f[i][j-v[i]]的表达…...
小白入门机器学习概述
文章目录 一、引言二、机器学习的基础概念1. 机器学习的定义2. 机器学习的类型(1)监督学习(Supervised Learning)(2)无监督学习(Unsupervised Learning)(3)半…...
深入了解 MySQL 锁机制
MySQL作为一个常用的关系型数据库系统,其事务处理能力强大,并提供了丰富的锁机制以保障数据的一致性和并发操作的有效性。在多用户并发操作的环境中,锁是控制资源访问的重要工具。本文将详细介绍MySQL中锁的分类及其具体应用,包括…...
ubuntu的ubuntu--vg-ubuntu--lv磁盘扩容
在我们安装ubuntu时,如果选择的是自动分区,就会按照逻辑卷的形式来分区,并且只分配100G其余的并不会被分配,这对我们大多数情况来说都是不合理的,所以,如何扩充呢 下面以一个小的案例来说明如何扩充 问题…...
音视频开发---常用工具
一、VLC播放器 1. 简介 VLC多媒体播放器(最初命名为VideoLAN客户端)是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘、VCD影音光盘和各类流式协议。它也能作为unicast或multicast的流式服务器在IPv4或IPv6的高速连接下使用。 它融…...
9、tlm 事务交互通信
1、TLM(Transaction-Level Modeling) 是 SystemC 的高级建模方法,用于描述系统的通信行为,特别是在硬件设计和验证中。TLM 是 SystemC 的一部分,用于提高仿真的效率和抽象性。以下是 TLM 的核心知识以及关键概念。 2、…...
Kotlin 基础语法解析
详细的 Kotlin 基础语法解析,结合概念说明和实用场景: 一、变量与常量 1. 变量类型 val(不可变变量):声明后不可重新赋值,类似 Java 的 final。 val name “Kotlin” // 类型自动推断为 String// name …...
MaxEnt模型进阶:基于R语言自动化与GIS空间建模的物种栖息地精准预测
生物多样性的空间分布规律及其对环境变化的响应机制,是生态学与地理学研究的前沿议题。在气候变化加剧和人类活动干扰的双重压力下,如何精准预测物种潜在分布范围、识别关键环境驱动因子,已成为制定生物保护策略的核心科学问题。物种分布模型…...
微软 GraphRAG 项目学习总结
微软2024年4月份发布了一篇《From Local to Global: A GraphRAG Approach to Query-Focused Summarization》(GraphRAG:从局部到全局的查询式摘要方法)论文,提出了一种名为GraphRAG的检索增强生成(RAG)方法…...
C# dataGridView 自动生成几行几列及手动输入整型字符
C# dataGridView生成12号4列的表格 private void Form1_Load(object sender, EventArgs e) {// 清除默认列dataGridView1.Columns.Clear();// 添加4列(首列为序号列)dataGridView1.Columns.Add("ColIndex", "序号");dataGridView1.…...
CSS层叠顺序
介绍 在 CSS 中,元素的层叠顺序决定了当多个元素重叠时(跟布局没有完全的关系,也就是说层叠顺序只会在几个叠放元素上进行比较,而不会改变布局),哪个元素显示在最上面,哪个元素显示在最下面。 …...
QtAV入门
QtAV 是一个基于 FFmpeg 和 Qt 的高性能多媒体播放框架,提供强大的音视频解码、渲染和处理能力,适合开发跨平台的播放器、视频编辑和流媒体应用。 1. 核心功能 多格式支持 支持 H.264/H.265、VP9、AV1 等视频编码。 支持 MP3、AAC、Opus 等音频编码。 封装格式:MP4、MKV、…...
Day17 -实例:利用不同语言不同框架的特征 进行识别
前置:我们所需的web站点,都可以利用fofa去搜索,例如:app"flask"这样的语句去找对应的站点,找到后,我们模拟不知道是什么框架,再根据特征去判断它的框架。 ***利用工具可以再去结合大…...
Pycharm(八):字符串切片
一、字符串分片介绍 对操作的对象截取其中一部分的操作,比如想要获取字符串“888666qq.com前面的qq号的时候就可以用切片。 字符串、列表、元组都支持切片操作。 语法:字符串变量名 [起始:结束:步长] 口诀:切片其实很简单,只顾头来…...
leetcode 53.Maximum Subarray
分治法 //lSum表示[left,right]内以left为左端点的最大子段和 //rSum表示[left,right]内以right为右端点的最大字段和 //iSum表示[left,right]的区间和 int divide_conquer(int* nums,int left,int right,int *lSum,int *rSum,int *iSum){int maxSum;//表示[left,right]内的最…...
Mysql从入门到精通day5————子查询精讲
本文主要讲述子查询的几种方法,读者注意体会它们的不同场合的适用情况及功能,本篇文章也融入了小编实践过程遇到的坑,希望读者不要再踩坑 一.带IN关键字的子查询 in关键字可以检测结果集中是否存在某个特定的值,检测成功则执行外…...
虫洞数观系列二 | Python+MySQL高效封装:为pandas数据分析铺路
目录 系列文章 1. 引言 2. 常规写法mysql 3. 封装设计接口mysql 3.1dbname.py文件 3.1.1. 导入和基类定义 3.1.2. 具体表定义类 3.1.3. 表定义整合函数 3.1.4. 全局字典和测试代码 3.2mysql_dao文件 3.2.1. 模块导入与配置 3.2.2. 数据库连接池初始化 3.2.3. Comm…...
算法刷题-最近公共祖先-LCA
AcWing 1172 祖孙询问 一、题目描述 给定一棵包含 n 个节点的有根无向树,节点编号互不相同,但不一定是 1∼n。 有 m 个询问,每个询问给出了一对节点的编号 x 和 y,询问 x 与 y 的祖孙关系。 输入格式 第一行一个整数 n 表示节…...
MySQl之Binlog
前言 Binlog(Binary Log)是MySQL中至关重要的日志模块,它直接关系到数据恢复、主从复制等高阶架构设计。无论你是刚入门的新手还是有一定经验的开发者,掌握Binlog的原理和应用都是进阶的必经之路。 BinLog是什么? Bin…...
