☰
结构型模式—桥接(Bridge)模式
2026/10/11 1:17:46 网站建设 项目流程

目录

  • 定义
  • 核心问题
    • 如何判断哪条是抽象链
  • 使用场景
  • 参与者
  • 优劣
  • 协作
  • 实现
  • 相关模式
  • 应用和思考

定义

桥接模式是将抽象部分和它的实现部分分离,使他们都可以独立的变化

核心问题

解决类继承的维度爆炸
当一个类型有两个独立变化的维度时,把两个维度都塞进继承树是灾难。通过下面例子说明:遥控器 x 电视品牌

  • 维度1(遥控器):你手里的按键语义——基础款几个键、高级款多静音键、音量步进更细
  • 维度2(电视):命令被真正执行的品牌协议——同样是"音量+",索尼和三星的红外编码完全不同,换台电视整套换。

关键在于两层互相不认识:按键语义不需要知道红外编码,红外编码也不关心你按的是哪个键。

```text 继承方案(专用遥控器爆炸): 桥接方案: Remote Remote ◀── Basic/Advanced ←维度1├── SonyBasicRemote │ 持有 tv_(唯一一条桥) ├── SonyAdvancedRemote ▼ ├── SamsungBasicRemote Tv ◀── Sony/Samsung/Virtual ←维度2└── SamsungAdvancedRemote
  • n款显示器 x m个品牌:继承要n x m个专用型号,桥接模式下只需要n + m个类
  • 接入一个新品牌(小米/华为):继承要把遥控器系全部重做(再加n个型号);桥接加1个协议类
  • 更隐蔽的害处:继承方案里SonyAdvancedRemote这种类名本身就是两个维度相乘的记号——看到"类名 = 维度1×维度2"就该条件反射想到桥接。

继承(专用型号)桥接
加品牌前(2×2)4 个叶子2 + 2 = 4 个具体类
加华为、小米后2×4 = 8 叶(+4 类)2 + 4 = 6 类(+2 类)
华为协议要写几遍2 遍(改协议改两处)1 遍(两款遥控器免费复用)
遥控器侧改动4 个新类0
再加第 3 档遥控器再加 4 个类再加 1 个类

“桥”的精确含义:两条继承链(抽象链,实现链)之间,原本需要 n x m条继承边连接;桥接后只剩一条组合边。

  1. 两条继承链并没有被消灭,而是保留且各自继续生长。bridge干掉的是错误的结构:用一棵继承树同时表达两个维度,把跨维度的那条边从“is-a"改成"has-a"
  2. 不只是静态结构重构,若把bridge只理解为整理继承关系,会漏掉组合带来的动态福利:
  • 运行期换bridge
  • 编译防火墙
  • 实现链对抽象链的单向无知(依赖倒置)

适用边界

  1. 前提是两个维度正交(可自由组合),若有配套约束,该换抽象工厂
  2. k个维度就是k个bridge,原理不变

Bridge就是把维度相乘的一棵继承树重构为维度相加的多棵独立继承树+一条组合边;继承没有消失,只是退回到它擅长的领域,跨维度的耦合交给了组合

如何判断哪条是抽象链

判据抽象链(Abstraction)实现链(Implementor)
词汇表业务名词:Remote、Telemetry——“这是什么”机制名词:Tv、Transport——“用什么做”
客户可见性客户代码直接使用仅组装根可见,客户代码零出现
变化驱动力业务需求(加一款遥控器/遥测源)技术选型(换品牌/换 DDS)
持有桥✓ 基类持有Implementor*成员✗根本不知道抽象链存在
接口风格意图级命令:volume_up()、report(v)原语级操作:set_volume(p)、encode(what,v)

最硬的一条:依赖方向。桥的箭头永远从抽象指向实现

使用场景

  • 不希望在抽象和他的实现部分之间有一个固定的绑定关系,这种情况可能是因为,在程序运行时刻,实现部分应可以被选择或者切换
  • 抽象和实现都可以通过生成子类的方式加以扩充,这时Bridge模式使你可以对不同的抽象接口和实现部分进行组合,并分别对他们进行扩充
  • 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译(对抽象的实现进行修改,不需要桥接模式就可以实现?)
  • 想对客户完全隐藏抽象的实现部分。在C++中类的表示在类接口中是可见的
  • 有许多类要生成,这样的一种类层次结构说明必须将一个对象分解成两部分
  • 想在多个对象间共享实现,但同时要求客户不知道这一点——使用场景
  • 如果想拆分或重组一个具有多重功能的庞杂类,可以使用桥接模式
  • 如果希望在几个独立维度上扩展一个类,可以使用该模式

参与者

  • Abstraction:
    • 定义抽象类接口
    • 维护一个指向Implementor类型对象的指针
  • RefeinedAbstraction:扩充由Abstraction定义的接口
  • Implementor:定义实现类的接口,这些接口不一定要与Abstraction一致,事实上可以完全不同。一般来说Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作
  • ConcreImplementor:实现Implementor接口并定义它的具体实现

优劣

  • 优点
    • 两个维度独立扩展互不影响(开闭原则)
    • 运行期换实现
    • 抽象层与实现层编译隔离
    • 消除组合爆炸
  • 缺点
    • 多一层间接多一层转发
    • 需要预先识别出那两个维度会变,识别错了维度,bridge就是白搭
    • 小系统上直接 ** n x m ** 个类反而更加直白

协作

Abstraction将client的请求转发给它的Implementor对象

实现

  • 仅有一个Implementor:在仅有一个实现的时候,没有必要创建一个抽象的Implementor
  • 创建正确的Implementor对象:当存在多个Implementor类的时候,应该用何种方法,在何时何地创建哪个Implementor对象
  • 共享Implementor对象
  • 采用多重继承机制
  • 怎样将正确的Implementor对象传给Abstraction对象?怎样使用抽象工厂来创建和配置一个特定的Bridge模式

相关模式

  • 抽象工厂可以用来创建和配置一个特定的Bridge模式
  • Adapter模式用来帮助无关的类协同工作,他通常在系统设计完成后才会被使用,而Bridge模式在系统开始时就被使用,它使得抽象接口和实现部分可以独立进行改变

应用和思考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询