Adapter模式来源:
在实际应用中,将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。生活中笔记本电脑和手机等数码产品的充电器就是一个适配器,将家用220V的交流电转换为笔记本或手机正常工作所需的目标电压和电流。适配器起到一种转换和包装的作用。
Adapter模式作用:
Adapter设计模式主要目的组合两个不相干类,常用有两种方法:第一种解决方案是修改各自类的接口。但是如果没有源码,或者不愿意为了一个应用而修改各自的接口,则需要使用Adapter适配器,在两种接口之间创建一个混合接口。
Adapter适配器设计模式中有3个重要角色:被适配者Adaptee,适配器Adapter和目标对象Target。其中两个现存的想要组合到一起的类分别是被适配者Adaptee和目标对象Target角色,我们需要创建一个适配器Adapter将其组合在一起。
Adapter模式中的角色:
1. 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
2. 需要适配的类(Adaptee):需要适配的类或适配者类。
3. 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
共有两类适配器模式:
①对象适配器模式:
在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。是一种组合(compositon, has-a关系)。对象适配器模式使用组合,UML图如图1所示:
图1 对象适配器UML图
②类适配器模式:
这种适配器模式下,适配器继承自已实现的类(一般多重继承),是一种继承(inheritance,is-a关系)。UML图如如图2所示:
图2 类适配器UML图
代码示例如下:
Adapter.h #ifndef _ADAPTER_H_ #define _ADAPTER_H_ //目标接口类,客户需要的接口 class Target { public: Target(); virtual ~Target(); virtual void Request();//定义标准接口 }; //需要适配的类 class Adaptee { public: Adaptee(); ~Adaptee(); void SpecificRequest(); }; //类模式,适配器类,通过public继承获得接口继承的效果,通过private继承获得实现继承的效果 class Adapter :public Target, private Adaptee { public: Adapter(); ~Adapter(); virtual void Request();//实现Target定义的Request接口 }; //对象模式,适配器类,继承Target类,采用组合的方式实现Adaptee的复用 class Adapter1 :public Target { public: Adapter1(Adaptee* adaptee); Adapter1(); ~Adapter1(); virtual void Request();//实现Target定义的Request接口 private: Adaptee* _adaptee; }; #endif
Adapter.cpp #include "Adapter.h" #include <iostream> using namespace std; Target::Target() {} Target::~Target() {} void Target::Request() { cout << "Target::Request()" << endl; } Adaptee::Adaptee() { } Adaptee::~Adaptee() { } void Adaptee::SpecificRequest() { cout << "Adaptee::SpecificRequest()" << endl; } //类模式的Adapter Adapter::Adapter() { } Adapter::~Adapter() { } void Adapter::Request() { cout << "Adapter::Request()" << endl; this->SpecificRequest(); cout << "----------------------------" << endl; } //对象模式的Adapter Adapter1::Adapter1() :_adaptee(new Adaptee) { } Adapter1::Adapter1(Adaptee* _adaptee) { this->_adaptee = _adaptee; } Adapter1::~Adapter1() { } void Adapter1::Request() { cout << "Adapter1::Request()" << endl; this->_adaptee->SpecificRequest(); cout << "----------------------------" << endl; }</span>
main.cpp #include "Adapter.h" int main() { //类模式Adapter Target* pTarget = new Adapter(); pTarget->Request(); //对象模式Adapter1 Adaptee* ade = new Adaptee(); Target* pTarget1 = new Adapter1(ade); pTarget1->Request(); //对象模式Adapter2 Target* pTarget2 = new Adapter1(); pTarget2->Request(); return 0; }
Adapter模式使用总结:
在Adapter模式的两种模式中,有一个很重要的概念就是接口继承和实现继承的区别和联系。接口继承和实现继承是面向对象领域的两个重要的概念,接口继承指的是通过继承,子类获得了父类的接口,而实现继承指的是通过继承子类获得了父类的实现(并不提供接口)。在C++中的public继承既是接口继承又是实现继承,因为子类在继承了父类后既可以对外提供父类中的接口操作,又可以获得父类的接口实现。当然我们可以通过一定的方式和技术模拟单独的接口继承和实现继承,例如我们可以通过private继承获得实现继承的效果(private继承后,父类中的接口都变为private,当然只能是实现继承了),通过纯抽象基类模拟接口继承的效果,但是在C++中pure virtual function也可以提供默认实现,因此这是不纯正的接口继承,但是在Java中我们可以interface来获得真正的接口继承了。