桥接(桥梁)模式
简介
桥接模式(Bridge Pattern)又叫作桥梁模式、接口(Interface)模式或柄体(Handle and Body)模式,指将抽象部分与具体实现部分分离,使它们都可以独立地变化,属于结构型设计模式。
常用用于替换继成
通用模板
-
创建实现接口:确定实现维度的基本操作,提供给Abstraction使用。该类一般为接口或抽象类。
// 抽象实现 public interface IImplementor {void operationImp(); } -
创建具体实现类:Implementor的具体实现。
// 具体实现类A public class ConcreteImplementorA implements IImplementor{@Overridepublic void operationImp() {System.out.println("I am ConcreteImplementorA");} }// 具体实现类B public class ConcreteImplementorB implements IImplementor {@Overridepublic void operationImp() {System.out.println("I am ConcreteImplementorB");} } -
创建抽象类:该类持有一个对实现角色的引用,抽象角色中的方法需要实现角色来实现。抽象角色一般为抽象类(构造函数规定子类要传入一个实现对象)。
// 抽象 public abstract class Abstraction {private IImplementor iImplementor;public Abstraction(IImplementor iImplementor) {this.iImplementor = iImplementor;}public void operation() {iImplementor.operationImp();} } -
创建修正抽象类:Abstraction的具体实现,对Abstraction的方法进行完善和扩展。
// 修正抽象类 public class RefineAbstraction extends Abstraction {public RefineAbstraction(IImplementor iImplementor) {super(iImplementor);}@Overridepublic void operation() {super.operation();System.out.println("refine operation");} } -
创建修正实现类:RefineAbstraction的具体实现
// 修正抽象实现类 public class ConcreteRefineAbstractionA extends RefineAbstraction {public ConcreteRefineAbstractionA(IImplementor iImplementor) {super(iImplementor);}@Overridepublic void operation() {super.operation();System.out.println("ConcreteRefineAbstraction");} }
模板测试
-
测试代码
public class Client {public static void main(String[] args) {// 创建一个具体的角色ConcreteImplementorA imp = new ConcreteImplementorA();// 创建一个抽象的角色,聚合实现RefineAbstraction abs = new ConcreteRefineAbstractionA(imp);// 执行操作abs.operation();} } -
结果
I am ConcreteImplementorA refine operation ConcreteRefineAbstraction
应用场景
在生活场景中,桥接模式随处可见,比如连接起两个空间维度的桥、连接虚拟网络与真实网络的链接。
当一个类内部具备两种或多种变化维度时,使用桥接模式可以解耦这些变化的维度,使高层代码架构稳定。
桥接模式适用于以下几种业务场景。
(1)在抽象和具体实现之间需要增加更多灵活性的场景。
(2)一个类存在两个(或多个)独立变化的维度,而这两个(或多个)维度都需要独立进行扩展。 (3)不希望使用继承,或因为多层继承导致系统类的个数剧增。
注:桥接模式的一个常见使用场景就是替换继承。我们知道,继承拥有很多优点,比如,抽象、封装、多态等,父类封装共性,子类实现特性。继承可以很好地实现代码复用(封装)的功能,但这也是继承的一大缺点。因为父类拥有的方法,子类也会继承得到,无论子类需不需要,这说明继承具备强侵入性(父类代码侵入子类),同时会导致子类臃肿。因此,在设计模式中,有一个原则为优先使用组合/聚合,而不是继承。 很多时候,我们分不清该使用继承还是组合/聚合或其他方式等,其实可以从现实语义进行思考。因为软件最终还是提供给现实生活中的人使用的,是服务于人类社会的,软件是具备现实场景的。当我们从纯代码角度无法看清问题时,现实角度可能会提供更加开阔的思路。
优点
(1)分离抽象部分及其具体实现部分。
(2)提高了系统的扩展性。
(3)符合开闭原则。
(4)符合合成复用原则。
缺点
(1)增加了系统的理解与设计难度。
(2)需要正确地识别系统中两个独立变化的维度。
“生搬硬套”实战
场景描述
桥接模式的定义非常玄乎,直接理解不太容易,所以我们还是举例子。
假设某个汽车厂商生产三种品牌的汽车:Big、Tiny和Boss,每种品牌又可以选择燃油、纯电和混合动力。如果用传统的继承来表示各个最终车型,一共有3个抽象类加9个最终子类:

如果要新增一个品牌,或者加一个新的引擎(比如核动力),那么子类的数量增长更快。
所以,桥接模式就是为了避免直接继承带来的子类爆炸。
我们来看看桥接模式如何解决上述问题。
在桥接模式中,首先把Car按品牌进行子类化,但是,每个品牌选择什么发动机,不再使用子类扩充,而是通过一个抽象的“修正”类,以组合的形式引入。我们来看看具体的实现。
代码开发
-
创建实现(这里指引擎)接口
// 实现接口 public interface Engine {void start(); } -
创建具体实现(这里指的是各种引擎)类
// 混动引擎实现 public class HybridEngine implements Engine {public void start() {System.out.println("Start Hybrid Engine...");} }// 油引擎实现 public class FuelEngine implements Engine {public void start() {System.out.println("Start Fuel Engine...");} }// 纯电引擎实现 public class PureEngine implements Engine {public void start() {System.out.println("Start Pure Engine...");} } -
创建抽象(这里指的是车)类
// 抽象车类 public abstract class Car {// 引用Engine:protected Engine engine;public Car(Engine engine) {this.engine = engine;}public abstract void drive(); } -
创建修正抽象(这里指的是修正车类)类
// 修正车抽象类 public abstract class RefinedCar extends Car{public RefinedCar(Engine engine) {super(engine);}@Overridepublic void drive() {this.engine.start();System.out.println("Drive " + getBrand() + " car...");}public abstract String getBrand(); } -
创建修正实现(这里指具体不同品牌的车)类
// Boss品牌车 public class BossCar extends RefinedCar {public BossCar(Engine engine) {super(engine);}@Overridepublic String getBrand() {return "Boss";} }// Big品牌车 public class BigCar extends RefinedCar {public BigCar(Engine engine) {super(engine);}@Overridepublic String getBrand() {return "Big";} }// Tiny品牌车 public class TinyCar extends RefinedCar {public TinyCar(Engine engine) {super(engine);}@Overridepublic String getBrand() {return "Tiny";} }
至此,我们就通过“生搬硬套”桥梁模式的模板设计出一套替换继成的桥接模式代码,接下来我们进行测试:
-
测试代码
public class Test {public static void main(String[] args) {RefinedCar car = new BossCar(new HybridEngine());car.drive();} } -
结果
Start Hybrid Engine... Drive Boss car...
总结
使用桥接模式的好处在于,如果要增加一种引擎,只需要针对Engine派生一个新的子类,如果要增加一个品牌,只需要针对RefinedCar派生一个子类,任何RefinedCar的子类都可以和任何一种Engine自由组合,即一辆汽车的两个维度:品牌和引擎都可以独立地变化。

桥接模式实现比较复杂,实际应用也非常少,但它提供的设计思想值得借鉴,即不要过度使用继承,而是优先拆分某些部件,使用组合的方式来扩展功能。
相关文章:
桥接(桥梁)模式
简介 桥接模式(Bridge Pattern)又叫作桥梁模式、接口(Interface)模式或柄体(Handle and Body)模式,指将抽象部分与具体实现部分分离,使它们都可以独立地变化,属于结构型…...
语言模型发展史
四个阶段 第一阶段:基于规则和统计的语言模型 由人工设计特征并使用统计方法对固定长度的文本窗口序列进行建模分析,这种建模方式也被称为N-gram语言模型。 优点: 1)采用极大似然估计, 参数易训练 2)完全包含了前n-…...
【Linux】模拟实现一个shell
接受每一个人的批评,可是保留你自己的判断。 ——莎士比亚 一段时间的没有更新是由于最近开学期间比较的忙,同时也是由于刚开学的几门课才学习的时候有点迷糊,需要在学校课堂上花的时间更多了,所以才没有更新的,求放过…...
云原生数据库 PolarDB
简介:云原生数据库 PolarDB 是阿里云自研产品,在存储计算分离架构下,利用了软硬件结合的优势,为用户提供秒级弹性、高性能、海量存储、安全可靠的数据库服务。100%兼容MySQL和PostgreSQL生态,支持分布式扩展࿰…...
MobaXterm基本使用 -- 服务器状态、批量操作、显示/切换中文字体、修复zsh按键失灵
监控服务器资源 参考网址:https://www.cnblogs.com/144823836yj/p/12126314.html 显示效果 MobaXterm提供有这项功能,在会话窗口底部,显示服务器资源使用情况 如内存、CPU、网速、磁盘使用等: (完整窗口࿰…...
elastic Search 初步之向量检索的数据写入及检索查询
### Elasticsearch 向量检索实现方法方案 Elasticsearch 从 7.3 版本开始引入了向量检索功能,支持通过向量字段进行相似度搜索。以下是实现向量检索的步骤和方案,包括 Python 和 Java 版本的代码示例。 #### 1. 最低实现向量检索的 ES 版本 - **最低版本**: Elasticsearch …...
Tdesign TreeSelect 树形选择 多选
这里写自定义目录标题 小程序原生开发 Tdesign TreeSelect 树形选择 多选可以选择不同一级分类下的数据 小程序原生开发 Tdesign TreeSelect 树形选择 多选可以选择不同一级分类下的数据 TreeSelect 树形选择 在原demo基础上修改 const chineseNumber 一二三四五六七八九十.…...
Pygame中Sprite实现逃亡游戏5
在《Pygame中Sprite实现逃亡游戏4》中通过碰撞检测实现了玩家、飞龙与飞火之间的碰撞处理,基本上实现了逃亡功能。最后,实现这个逃亡游戏中文字提示的功能。 1 操作提示 当进入游戏后,会在玩家下方的位置给出操作提示,如图1所示…...
等保2.0数据库测评之达梦数据库测评
一、达梦数据库介绍 达梦数据库管理系统属于新一代大型通用关系型数据库,全面支持 ANSI SQL 标准和主流编程语言接口/开发框架。行列融合存储技术,在兼顾 OLAP 和 OLTP 的同时,满足 HTAP 混合应用场景。 本次安装环境为Windows10专业版操作…...
集成mcuboot后测试和验证的方法
本文介绍一些在实际项目中集成的 MCUboot后测试和验证的方法和步骤: 功能测试 启动测试 正常启动验证 : 多次上电启动设备,观察 MCUboot 是否能够正常加载并跳转到应用程序。检查启动过程中的日志输出(如果有)&#…...
Vulhub zico 2靶机详解
项目地址 https://download.vulnhub.com/zico/zico2.ova实验过程 将下载好的靶机导入到VMware中,设置网络模式为NAT模式,然后开启靶机虚拟机 使用nmap进行主机发现,获取靶机IP地址 nmap 192.168.47.1-254根据对比可知Zico 2的一个ip地址为…...
宠物医院微信小程序源码
文章目录 前言研究背景研究内容一、主要技术?二、项目内容1.整体介绍(示范)2.系统分析3.数据表信息4.运行截图5.部分代码介绍 总结 前言 随着当代社会科技的迅速发展,计算机网络时代正式拉来帷幕,它颠覆性的影响着社会…...
[教程]Crystal源码下载及编译
描述: 随着 Crystal Source 代码的更新,用于构建源代码和编译它们的指南已经过时,这导致了很多混淆和寻求帮助。 本指南将是一个完整的分步指南,从下载 Visual Studio 到启动到您的服务器。 此外,请确保下载此存储库中…...
【Android 14源码分析】WMS-窗口显示-流程概览与应用端流程分析
忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。 – 服装…...
双指针---(部分地更新)
双指针 复写零 给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。 注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。 …...
【Windows】自定义显示器的分辨率
背景 由于本人更新驱动导致2个显示器里面,有一个显示器的分辨率只剩下2个可以调节 这样就导致2个显示器分辨率不同,更新了多次驱动都修复不了,所以想着看能不能自定义分辨率 工具下载 显示器自定义分辨率工具 或者百度搜索 Custom Resolu…...
组播基础-2-IGMP协议
文章目录 IGMPIGMPv1IGMPv2IGMPv3IGMP总结IGMP Snooping IGMP 运行于主机和路由器之间 因特网组管理协议,TCP/IP 协议族中负责 IP 组播成员管理的协议,用来在接收者与其他直接相邻的组播路由器之间建立、维护组播组成员关系 负责组播成员管理…...
基于Springboot+Vue的视频点播系统设计与实现登录 (含源码数据库)
1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统中…...
执行力怎么培养?
执行力怎么培养? 并行:适合在初期养成习惯,不抱对结果的期望天才就是强迫症:适合中期修身:适合高级 并行:适合在初期养成习惯,不抱对结果的期望 在你开始做任何事情的时候,不要一开…...
Power apps:一次提交多项申请
1、添加一个Form,导入sharepoint列表,添加确认,继续,取消按钮 2、在页面的onvisible属性中添加 Set(applynumber,Last(付款申请表).申请编号1); #定义一个申请编号变量,每次申请,就将列表最后一个…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
