桥接模式将抽象(Abstraction)与实现(Implementation)分离,使得两者能够独立地变化。ios
桥接模式将抽象和实现分别独立实现,即Abstraction类和Implement类。编程
桥接模式中的实现不是指抽象基类的具体子类对抽象基类中虚函数(接口)的实现,是指怎么去实现用户的需求,即在Implement具体类中实现Abstraction的接口功能,而且是经过组合(委托)的方式实现的,所以桥接模式中实现不是指的继承基类、实现基类接口,而是指的是经过对象组合实现用户的需求。设计模式
桥接模式将继承关系转换为组合关系,从而下降了系统间的耦合,减小了代码编写量。使用组合(委托)的方式将抽象和实现完全地解耦,好处是抽象和实现能够分别独立地变化,系统的耦合性也获得了很好的下降。app
将抽象部分与它的实现部分分离,使得它们能够独立地变化。抽象Abstraction与实现Implement分离,抽象部分Abstraction能够变化,如new RefinedAbstractionA(imp)、new RefinedAbstractionB(imp);实现部分Implement也能够独立变化,如new ConcreteImplementA()、new ConcreteImplementB()。ide
抽象类(Abstraction):定义抽象类接口而且维护一个指向Implement的指针函数
扩充抽象类(RefinedAbstraction):扩充由Abstraction定义的接口ui
实现类接口(Implement):定义实现类的接口,该接口不必定要与 Abstraction的接口彻底一致;事实上这两个接口能够彻底不一样。通常来说, Implement接口仅提供基本操做,而 Abstraction则定义了基于这些基本操做的较高层次的操做。spa
具体实现类(ConcreteImplement):实现Implement接口并定义具体实现。操作系统
Abstraction::request():定义要实现的操做接口,在Abstraction::request()中根据不一样的指针多态调用Implement::operation()函数。.net
Implement::operation():实现抽象类Abstaction所定义操做的接口,由其具体派生类ConcreteImplemenA、ConcreteImplemenB或者其余派生类实现。
优势:
A、分离接口及其实现部分 。一个实现未必不变地绑定在一个接口上。抽象类的实现能够在运行时刻进行配置,一个对象甚至能够在运行时刻改变它的实现。将Abstraction与Implement分离有助于下降对实现部分编译时刻的依赖性,当改变一个实现类时,并不须要从新编译Abstraction类和它的客户程序。为了保证一个类库的不一样版本之间的二进制兼容性,必定要有这个性质。另外,接口与实现分离有助于分层,从而产生更好的结构化系统,系统的高层部分仅需知道Abstraction和Implement便可。
B、提升可扩充性 。能够独立地对Abstraction和Implement层次结构进行扩充。
C、实现细节对客户透明 。能够对客户隐藏实现细节,例如共享Implement对象以及相应的引用计数机制。
D、将能够共享的变化部分,抽离出来,减小了代码的重复信息。
E、对象的具体实现能够更加灵活,能够知足多个因素变化的要求。
缺点:
A、桥接模式的引入会增长系统的理解与设计难度,因为聚合关联关系创建在抽象层,要求开发者针对抽象进行设计与编程。
B、桥接模式要求正确识别出系统中两个独立变化的维度,所以其使用范围具备必定的局限性。
C、客户必须知道选择哪种类型的实现。
桥接模式使用场景:
A、当一个对象有多个变化因素的时候,考虑依赖于抽象的实现,而不是具体的实现。如手机品牌有2种变化因素,一个是品牌,一个是功能。
B、当多个变化因素在多个对象间共享时,考虑将变化的部分抽象出来再聚合或组合进来。
C、当考虑一个对象的多个变化因素能够动态变化的时候,考虑使用桥接模式,如手机的手机品牌是变化的,手机的功能也是变化的,因此将每一个可变化的因数分离出来,独立的变化。
抽象工厂模式能够用来建立和配置一个特定的桥接模式。
适配器模式用来帮助无关的类协同工做,一般在系统设计完成后才会被使用。然而,桥接模式则是在系统开始时就被使用,使得抽象接口和实现部分能够独立进行改变。
桥接模式和装饰模式在必定程度上都是为了减小子类的数目,避免出现复杂的继承关系,但解决的方法却各有不一样。装饰模式把子类中比基类中多出来的部分放到单独的类里面,以适应新功能增长的须要,当把描述新功能的类封装到基类的对象里面时,就获得所须要的子类对象,描述新功能的类经过组合能够实现不少的功能组合。 桥接模式则把原来的基类的实现化细节抽象出来,在构造到一个实现化的结构中,而后再把原来的基类改形成一个抽象化的等级结构,就能够实现系统在多个维度上的独立变化 。
Abstraction基类:
#ifndef ABSTRACTION_H #define ABSTRACTION_H #include "Implement.h" //抽象基类 class Abstraction { public: //须要实现的接口 virtual void request() = 0; protected: Abstraction(Implement* imp):m_implement(imp){} protected: Implement* m_implement; }; #endif // ABSTRACTION_H
RefinedAbstractionA具体类:
#ifndef REFINEDABSTRACTIONA_H #define REFINEDABSTRACTIONA_H #include "Abstraction.h" #include <iostream> #include "Implement.h" using namespace std; class RefinedAbstractionA : public Abstraction { public: RefinedAbstractionA(Implement* imp):Abstraction(imp){} virtual void request() { cout << "RefinedAbstractionA::request" << endl; //调用实现部分 m_implement->operation(); } }; #endif // REFINEDABSTRACTIONA_H
RefinedAbstractionB具体类:
#ifndef REFINEDABSTRACTIONB_H #define REFINEDABSTRACTIONB_H #include "Abstraction.h" #include <iostream> #include "Implement.h" using namespace std; class RefinedAbstractionB : public Abstraction { public: RefinedAbstractionB(Implement* imp):Abstraction(imp){} virtual void request() { cout << "RefinedAbstractionB::request" << endl; //调用实现部分 m_implement->operation(); } }; #endif // REFINEDABSTRACTIONB_H
Implement抽象实现类:
#ifndef IMPLEMENT_H #define IMPLEMENT_H //抽象实现类 class Implement { public: virtual void operation() = 0; protected: Implement(){} }; #endif // IMPLEMENT_H
ConcreteImplementA具体实现类:
#ifndef CONCRETEIMPLEMENTA_H #define CONCRETEIMPLEMENTA_H #include "Implement.h" #include <iostream> using namespace std; //具体实现类 class ConcreteImplementA : public Implement { public: //具体实现的功能函数 void operation() { cout << "ConcreteImplementA::operation()" << endl; } }; #endif // CONCRETEIMPLEMENTA_H
ConcreteImplementB具体实现类:
#ifndef CONCRETEIMPLEMENTB_H #define CONCRETEIMPLEMENTB_H #include "Implement.h" #include <iostream> using namespace std; //具体实现类 class ConcreteImplementB : public Implement { public: //具体实现的功能函数 void operation() { cout << "ConcreteImplementB::operation()" << endl; } }; #endif // CONCRETEIMPLEMENTB_H
客户调用程序:
#include "Abstraction.h" #include "Implement.h" #include "ConcreteImplementA.h" #include "ConcreteImplementB.h" #include "RefinedAbstractionA.h" #include "RefinedAbstractionB.h" int main() { Implement* imp = new ConcreteImplementA(); Abstraction* abs = new RefinedAbstractionA(imp); abs->request(); Implement* imp1 = new ConcreteImplementB(); Abstraction* abs1 = new RefinedAbstractionB(imp1); abs1->request(); return 0; }
将抽象部分与实现部分分离:实现系统可能有多角度(维度)分类,每一种分类均可能变化,把多种角度分离出来让它们独立变化,减小它们之间的耦合。
在发现须要多角度去分类实现对象,而只用继承会形成大量的类增长,不能知足开放-封闭原则时,要考虑用桥接模式。
组合/聚合复用原则:尽可能使用组合/聚合,不要使用类继承。
优先使用对象的组合/聚合将有助于保持每一个类被封装,并被集中在单个任务上。类和类继承层次会保持较小规模,而且不太可能增加为不可控制的庞然大物。
电脑品牌和操做系统是两个概念,不一样的品牌的电脑能够安装相同或不一样的操做系统,二者都具备很大的变更性。若是单独以电脑品牌或操做系统为基类来进行继承扩展的话,会使类的数目剧增而且耦合性很高,若是更改电脑品牌或增长操做系统类型都会增长不少的变更。
将二者抽象出来两个基类分别是Computer和OS,在Computer类中聚合一个OS对象的基类将解决电脑品牌和操做系统扩展混乱的问题,二者的扩展就相对灵活,剪短了二者的必要联系。
Computer接口:
#ifndef COMPUTER_H #define COMPUTER_H class OS; class Computer { public: virtual void installOS(OS* os) = 0; }; #endif // COMPUTER_H
AppleComputer具体实现:
#ifndef APPLECOMPUTER_H #define APPLECOMPUTER_H #include "Computer.h" #include "OS.h" class AppleComputer : public Computer { public: virtual void installOS(OS* os) { cout << "AppleComputer "; os->installOS_Imp(); } }; #endif // APPLECOMPUTER_H
ThinkPadComputer具体实现:
#ifndef THINKPADCOMPUTER_H #define THINKPADCOMPUTER_H #include "Computer.h" #include "OS.h" class ThinkPadComputer : public Computer { public: virtual void installOS(OS* os) { cout << "ThinkPadComputer "; os->installOS_Imp(); } }; #endif // THINKPADCOMPUTER_H
OS接口:
#ifndef OS_H #define OS_H #include <iostream> using namespace std; class OS { public: virtual void installOS_Imp() = 0; }; #endif // OS_H
LinuxOS具体实现:
#ifndef LINUXOS_H #define LINUXOS_H #include "OS.h" class LinuxOS : public OS { public: virtual void installOS_Imp() { cout << "has installed Linux OS" << endl; } }; #endif // LINUXOS_H
WindowsOS具体实现:
#ifndef WINDOWSOS_H #define WINDOWSOS_H #include "OS.h" class WindowsOS : public OS { public: virtual void installOS_Imp() { cout << "has installed Windows OS" << endl; } }; #endif // WINDOWSOS_H
客户调用程序:
#include "OS.h" #include "Computer.h" #include "LinuxOS.h" #include "WindowsOS.h" #include "AppleComputer.h" #include "ThinkPadComputer.h" int main() { OS* lin = new LinuxOS(); OS* win = new WindowsOS(); Computer* apple = new AppleComputer(); Computer* thinkpad = new ThinkPadComputer(); apple->installOS(lin); apple->installOS(win); thinkpad->installOS(win); thinkpad->installOS(lin); delete lin,win,apple,thinkpad; return 0; }