桥接模式,是一种结构型的设计模式,设计的关键就在于能否解耦。
Intent 意图
Decouple an abstraction from its implementation so that the two can vary independently. 将抽象和实现解耦,让它们之间可以独立变化。
一个类存在两个(或多个) 独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。双方都只依赖于抽象,而不依赖于具体实现。
Motivation 动机
将继承关系转化为组合的关系,降低了系统间的耦合,减少系统复杂和代码编写。
Applicability 适用范围
- 拆分或者重组一个或者多重功能的复杂类,将一个复杂类拆分成几个类层次,从而实现修改任意一个类层次结构不影响其他类结构。
- 在几个独立维度拓展一个类
Structure 结构
Decouple an abstraction from its implementation so that the two can vary independently. 将抽象和实现解耦,让它们之间可以独立变化。
注:这里的抽象并非指的是抽象类或者接口的定义,而是将一些共性的内容进行抽取、整合,从而有了一个忽略具体细节的抽象体。调用方无需具体了解某个细节,而是将这些对于细节处理不同的东西,是做同样的一个抽象体使用即可。
Participate 结构成员
结构中各个类、对象所扮演的角色
- 抽象部分 (Abstraction) 提供高层控制逻辑,抽象化定义,并保存一个实现部分对象的引用,实际上依赖于完成底层实际工作的实现对象 (implementation)。
- 精确抽象 (Refined Abstraction) 与其父类(抽象部分)一样, 它们通过通用实现接口与不同的实现进行交互,是修正父类的一些抽象化定义。
- 实现对象 (Implementation) 为所有具体实现声明通用接口。 抽象部分仅能通过在这里声明的方法与实现对象交互,实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的抽象操作
- 具体实现 (Concrete Implementations) 中包括特定于平台的代码,即,在具体平台或者环境中,实现实现对象 (Implementation) 中所定义的接口方法。
- 通常情况下, 客户端 (Client) 仅关心如何与抽象部分合作,不关心具体实现差异或者平台差异。
Cooperation 协作
- 实现对象不一定和抽象部分接口定义相同,抽象部分可以列出和实现部分一样的方法, 但是抽象部分通常声明一些复杂行为, 这些行为依赖于多种由实现部分声明的原语操作。 (e.g. abstraction.feature1 = implementation.method1 & method2 )。
Consequence 后果
- Good
- 客户端仅和高层抽象做互动,不会接触到底层信息
- 符合单一职责和开闭
- 抽象和实现都可以进行独立拓展
- Bad
- 系统复杂度增加
Implementation 示例
如果使用 类 来进行拓展,当出现多个维度的时候,如下例,一个几何体拥有 shape & color 两个维度,如果想要表达红色的正方体,那就需要新建一个类,保存 shape & color,而如果再加上质量、粗糙 or 光滑 等等不同维度属性,则系统内的类的数量就会大爆炸。
而,如果我们将属性,通过组合的形式,组合起来,shape 里面包含一个 color 属性,而具体 color 以组合的方式传入。
Known uses 已知应用
JDBC 数据库驱动等等
Related Pattern 和其他模式直接的关系
桥接、适配器、策略、状态
- 都是基于组合的方式,将工作委派给其他对象,但是各自的意图不同。
- 桥接:解耦实现,实现相互依赖的类可以独立变化
- 适配器:改变一个类的接口,实现兼容
- 策略:提供多个可以相互替代的方法
- 状态:封装基于状态的行为,使用委托进行行为的切换
// 实现部分的抽象接口定义
interface MsgRender {
send(msg: string): void
}
// 具体实现对象
class PhoneMsgRender implements MsgRender {
private phoneNumber = []
constructor(phones?: string[]) {
this.phoneNumber = phones ?? []
}
send(msg: string): void {
console.log('phoning')
console.log(`${msg}`)
}
}
class EmailMsgRender implements MsgRender {
private emailAddress = []
constructor(emailAddress?: string[]) {
this.emailAddress = emailAddress ?? []
}
send(msg: string): void {
console.log('emailing')
console.log(`${msg}`)
}
}
// 抽象部分
abstract class Notification {
// key method 持有实现对象的引用
protected msgRender: MsgRender
constructor(msgRender: MsgRender) {
this.msgRender = msgRender
}
abstract notify(msg: string): void
}
// 可以理解为 refine abstration 抽象部分的修正
class DangerNotificaton extends Notification {
message: string = '[Warning]'
constructor(msgRender: MsgRender) {
super(msgRender)
}
notify(msg: string): void {
this.msgRender.send(`${this.message}: ${msg}`)
}
}
// 可以理解为 refine abstration 抽象部分的修正
class InfoNotificaton extends Notification {
message: string = '[Info]'
constructor(msgRender: MsgRender) {
super(msgRender)
}
notify(msg: string): void {
this.msgRender.send(`${this.message}: ${msg}`)
}
}
// context
const dangerNotificaton = new DangerNotificaton(new PhoneMsgRender())
dangerNotificaton.notify('The error count reach limited number')
const infoNotificaton = new InfoNotificaton(new EmailMsgRender())
infoNotificaton.notify('The error count reach limited number')