意图
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
动机
当一个抽象可能有多个实现时,通常用继承来协调它们。抽象类定义对该抽象的接口,而具体的子类则用不同方式加以实现。但是此方法有时不够灵活。继承机制将抽象部分与它的实现部分固定在一起,使得难以对抽象部分和实现部分独立的进行修改、扩充和重用。桥接模式把依赖具体实现,提升为依赖抽象,来完成对象和变化因素之间的低耦合,提高系统的可维护性和扩展性。桥接模式的主要目的是将一个对象的变化与其它变化隔离开,让彼此之间的耦合度最低。
适用性
- 如果不希望在抽象和它的实现部分之间有一个固定的绑定关系,也就是继承关系;如果我们打破了这种固定的绑定关系,以后,就可以方便的在抽象部分切换不同的实现部分;
- 如果希望类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充;如果不使用桥接模式,使用继承去实现时,在抽象类中添加一个方法,则在对应的实现类中也需要做对应的改动,这种实现不符合松耦合的要求;
- 如果要求对一个抽象的实现部分的修改对客户不产生影响,即客户的代码不需要重新编译,在后面的项目经验会说这方面;
- 如果想对客户完全隐藏抽象的实现部分;
- 如果一个对象有多个变化因素的时候,通过抽象这些变化因素,将依赖具体实现,修改为依赖抽象;
- 如果某个变化因素在多个对象中共享时,可以抽象出这个变化因素,然后实现这些不同的变化因素。
上面使用的场景,是一种建议,也是一种参考。在项目中要很好的把握一个设计模式,是有一定的难度的;当在实际项目中遇到满足上面的一点或者几点时,可以考虑使用桥接模式。
结构
Abstraction类定义了抽象类的接口,并且维护一个指向Implementor实现类的指针;
RefineAbstraction类扩充了Abstraction类的接口;
Implementor类定义了实现类的接口,这个接口不一定要与Abstraction的接口完全一致;实际上,这两个接口可以完全不同;
ConcreteImplementor类实现了Implementor定义的接口。
实现
1 #include <iostream> 2 using namespace std; 3 class Implementor 4 { 5 public: 6 virtual void OperationImpl() = 0; 7 }; 8 class ConcreteImpementor : public Implementor 9 { 10 public: 11 void OperationImpl() 12 { 13 cout << "OperationImpl" << endl; 14 } 15 }; 16 class Abstraction 17 { 18 public: 19 Abstraction(Implementor *pImpl) : m_pImpl(pImpl){} 20 virtual void Operation() = 0; 21 protected: 22 Implementor *m_pImpl; 23 }; 24 class RedfinedAbstraction : public Abstraction 25 { 26 public: 27 RedfinedAbstraction(Implementor *pImpl) : Abstraction(pImpl){} 28 void Operation() 29 { 30 m_pImpl->OperationImpl(); 31 } 32 }; 33 int main(int argc, char *argv[]) 34 { 35 Implementor *pImplObj = new ConcreteImpementor(); 36 Abstraction *pAbsObj = new RedfinedAbstraction(pImplObj); 37 pAbsObj->Operation(); 38 delete pImplObj; 39 pImplObj = NULL; 40 delete pAbsObj; 41 pAbsObj = NULL; 42 return 0; 43 }