4.2-Bridge「Handle」-桥接-结构型模式
又称 Handle/Body
0.1.1 用途
将抽象部分与它的实现部分分离,使它们可以独立地变化。 继承 VS Bridge:
0.1.2 示例
场景:一个 GUI 工具箱中的可移植窗口需要支持 XWindows 和 PM 系统 实现方法:
- 继承:定义 Window 抽象类和它的两个子类 XWindow 与 PMWindow,由它们分别实现不同系统平台上的 Window 界面。
- 缺陷:
- 扩展 Window 抽象使之适用于不同种类的窗口或新的系统平台很不方便(需要为 Windows 的每个子类针对每个平台分别创建一个类)
- 继承机制使得客户代码与平台相关。
- 缺陷:
- Bridge 模式:将接口抽象和实现放在彼此独立的类层次结构中:
- 对 Window 子类的所有操作都是用 WindowImp 接口中的抽象操作实现的
- 将 Window 与 WindowImp 之间的关系称为桥接,它在抽象类与它的实现之间起到了桥梁作用,使它们可以独立地变化。

0.1.3 适用性
- 不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如,这种情况可能是因为,在程序运行时实现部分应可以被选择或者切换。
- 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时 Bridge 模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
- 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
- (C++)你想对客户完全隐藏抽象的实现部分。在 C++中,类的表示在类接口中是可见的。
- 若采用继承模式会有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。
- Rumbaugh 称这种类层次结构为“嵌套的泛化”(nested generalization) [RBP+91]。
- 你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。
0.1.4 结构

- Abstraction:抽象接口(例如示例中的 Window),维护一个指向实现(Implementor)的指针
- RefinedAbstraction:精化的接口(例如示例中的 IconWindow)
- Implementor:实现类的接口(示例中的 WindowImp)
- 该接口无需和 Abstraction 的接口一致。一般来讲:
- Implementor 接口仅提供基本操作
- Abstraction 则定义了基于这些基本操作的较高层次的操作
- 该接口无需和 Abstraction 的接口一致。一般来讲:
- ConcreteImplementor:实现 Implementor 的具体接口(示例中的 XWindowImp、PMWindowImp)
Abstraction 将 client 的请求转发给它的 Implementor 对象
0.1.5 优缺点
- 分离接口及其实现部分,抽象类的实现可以在运行时进行配置、变更
- (用于确保一个类库不同版本之间的兼容性)有助于降低对实现部分编译时的依赖性,当改变一个实现类时,并不需要重新编译 Abstraction 类和它的客户程序。
- 接口与实现分离有助于分层,从而产生更好的结构化系统
- 提高可扩充性你可以独立地对 Abstraction 和 Implementor 层次结构进行扩充
- 实现细节对客户透明 (可以对客户隐藏实现细节)
- 例如在 C++中,Implementor 类的类接口可以在一个私有的头文件中定义,这个文件不提供给客户。这样你就对客户彻底隐藏了一个类的实现部分。
0.1.6 实现
- 在仅有一个实现的时候,没有必要创建一个抽象的 Implementor 类
- 创建合适的 Implementor 类有多种方法:
- 指定特定的 ConcreteImplementor 类:如果 Abstraction 知道所有的 ConcreteImplementor 类,它就可以在它的构造器中对其中的一个类进行实例化
- 指定缺省实现,并根据需要切换实现:例如将容器起初初始化为数组,容量过大后切换为 hash 表
- 由代理对象决定:例如 AbstractFactory 模式中的选择窗口样式的工厂类
- C++中无法使用多重继承实现真正的 Bridge 模式(会把接口和特定实现绑定):public 继承接口,private 继承实现
- 共享 Implementor 对象:CPP 中常用 Handle/Body 的方法在对象之间共享实现(通过重载赋值运算符执行引用计数)