桥接
将抽象部分与它的实现部分放在两个不同的类层次中,使它们都可以独立地变化。
适用性
- 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如,这种情况可能是因为,在程序运行时刻实现部分应可以选择或者切换。
- 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时Bridge使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
- 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
- 你想对客户完全隐藏抽象的实现部分。在C++中,类的表示在类接口中是可见的。
- 想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。
示例情境
遥控器有不同的界面,针对不同电视又有不同的实现。
结构
Abstraction - 定义抽象类的接口。维护一个指向Implementor类型对象的指针。
RefinedAbstraction - 扩充由Abstraction定义的接口。
Implementor - 定义实现类的接口,该接口不一定要与Abstraction的接口完全一致;事实上这两个接口可以完全不同。一般来讲,Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。
ConcreteImplementor - 实现Implementor接口并定义它的具体实现。
协作:
Abstraction将Client的请求转发给它的Implementor对象。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| #include <iostream>
class Implementor { public: virtual void operation_imp() { std::cout<<"abstract imp."<<std::endl; } };
class ConcreteImplementorA : public Implementor { public: virtual void operation_imp() { std::cout<<"Concrete ImplementationA."<<std::endl; } };
class ConcreteImplementorB : public Implementor { public: virtual void operation_imp() { std::cout<<"Concrete ImplementationB."<<std::endl; } };
class Abstraction { public: Abstraction(Implementor* imp): m_imp(imp){} virtual void operation() { if (!m_imp) return; m_imp->operation_imp(); } protected: Implementor* m_imp; };
class RefinedAbstraction : public Abstraction { public: RefinedAbstraction(Implementor* imp) : Abstraction(imp){} virtual void additional_operation() { operation(); std::cout<<"I'm additional."<<std::endl; } };
int main() { ConcreteImplementorA a; ConcreteImplementorB b; Abstraction interface1(&a); RefinedAbstraction interface2(&b); interface1.operation(); interface2.operation(); interface2.additional_operation(); system("Pause"); };
|
优点
- 将实现予以解耦,让它和界面之间不再永久绑定。
- 抽象和实现可以独立扩展,不会影响到对方。
- 对于“具体的抽象类”所做的改变,不会影响到客户。
用途和缺点
- 适合使用在需要跨越多个平台的图形和窗口系统上。
- 当需要用不同的方式改变接口和实现时,你会发现桥接模式很好用。
- 桥接模式的缺点是增加了复杂度。
相关模式
- Abstract Factory模式可以用来创建和配置一个特定的Bridge模式。
- Adapter模式用来帮助无关的类协同工作,它通常在系统设计完成后才会被使用。然而,Bridge模式则是在系统开始时就被使用,它使得抽象接口和实现部分可以独立进行改变。
[1] 设计模式:可复用面向对象软件的基础
[2] Head First 设计模式