结构型模式 Bridge模式(桥模式)
一. 意图
将抽象部分与它的实现部分分离,使它们都可以独立地变化
二. 适用性
2.1. 你不希望在抽象和它的实现部分之间有一个固定的绑定关系. 例如这种情况可能是因为, 在程序运行时刻实现部分应可以被选择或者切换.
2.2. 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时Bridge模式使你可以对不同的抽象接口和实现部分进行组合, 并分别对它们进行扩充.
2.3. 对一个抽象的实现部分的修改应对客户不产生影响, 即客户的代码不必重新编译。
2.4. (C++)你想对客户完全隐藏抽象的实现部分. 在C++中, 类的表示在类接口中是可见的。
2.5. 正如在意图一节的第一个类图中所示的那样, 有许多类要生成. 这样一种类层次结构说明你必须将一个对象分解成两个部分。Rumbaugh称这种类层次结构为“嵌套的普化”(nested generalizations).
2.6. 你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点.
三. 模式结构
图1
四. 角色
Abstraction
定义抽象类的接口.
维护一个指向Implementor类型对象的指针.
RefinedAbstraction
扩充由Abstraction定义的接口.
Implementor
定义实现类的接口. 一般来讲Implementor接口仅提供基本操作, 而Abstraction则定义了基于这些基本操作的较高层次的操作.
ConcreteImplementor
实现Implementor接口并定义它的具体实现.
Client
Abstraction将Client的请求转发给它的Implementor对象.
五. 说明
Abstraction将Client的请求转发给它的Implementor对象.
1. 在Abstraction与Implementor之间有一种一对一的关系. 尽管如此, 当你希望改变一个类的实现不会影响已有的客户程序时, 模式的分离机制还是非常有用的, 也就是说, 不必重新编译它们, 仅需重新连接即可.
2. 创建正确的Implementor对象当存在多个Implementor类的时候, 你应该用何种方法, 在何时何处确定创建哪一个Implementor类呢?
如果Abstraction知道所有的ConcreteImplementor类, 它就可以在它的构造器中对其中的一个类进行实例化,它可以通过传递给构造器的参数确定实例化哪一个类. 我们也可以使用相关的工厂模式来创建, 这样Abstraction可以不需要知道具体的Implementor
六. 我的理解
1. 该模式的目的是将抽象部分与它的实现部分分离,使它们都可以独立地变化.
A. 如果不分离, 假设有3个抽象部分和4种实现部分, 3 * 4 = 12 需要12个类, 而且这些类有很多重合的地方.
如果分离了, 则需要 3 + 4 = 7个类, 通过这7个类来组合成12个不同的功能的对象(把一个维度分离成两个维度(抽象维度和实现维度)).
2. 抽象与实现不是简单的分离, 抽象需要调用实现, 这是一个关系. 是一种聚合关系, 而不是组合关系(当然你可以任意组合抽象与实现的各个类)
3. 一般来讲Implementor接口仅提供基本操作, 而Abstraction则定义了基于这些基本操作的较高层次的操作. 所以在设计时要一定要注意正确分离抽象与实现, 而且注意实现的粒度.
七. 相关模式
7.1 Abstract Factory 模式可以用来创建和配置一个特定的Bridge模式(实现维度的对象可以使用Abstract Factory来创建)。
7.2 Adapter模式用来帮助无关的类协同工作, 它通常在系统设计完成后才会被使用. 然而, Bridge模式则是在系统开始时就被使用, 它使得抽象接口和实现部分可以独立进行改变.