我们笔记本电脑的工作电压是20V,而家庭额定电压220V,如何让20V的笔记本电脑能够在220V的电压下工作?为了解决这种问题,我们引入了一个电源适配器(AC Adapter),俗称充电器,有了这个电源适配器,生活用电和笔记本电脑即可兼容
同样在软件开发中,有时也存在类似这种不兼容的情况,我们也可以像引入一个电源适配器一样引入一个称之为适配器的角色来协调这些存在不兼容的结构,这种设计方案即为适配器模式。
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。——Gang of Four
模式中的角色
1 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
2 需要适配的类(Adaptee):需要适配的类或适配者类。
3 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
共有两类适配器模式:
①对象适配器模式
在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。
②类适配器模式
这种适配器模式下,适配器继承自已实现的类(一般多重继承)。
对象适配器”通过组合除了满足“用户期待接口”还降低了代码间的不良耦合。在工作中推荐使用“对象适配”。
#include <iostream> // 目标类 -=> 对应于目标抽象类,内含我们现在项目需要的接口 // 相当于20V的电压接口 class Target { public : virtual ~Target( ) { } virtual void Request( ) // 希望获得的系统接口 { std::cout <<"Target::Request" <<std::endl; } }; // 需要适配的类, 内含不符合要求的接口 // 相当于已经提供好的220V的电压插座接口 class Adaptee { public : void SpecialRequest( ) { std::cout <<"Adaptee::SpecialRequest..." <<std::endl; } }; // 获取接口的适配器类, // 适配后的符合要求的接口 // 将目标类Adatee中不符合要求的接口, 转换为Target中的接口类型 // 相当于一个转接器,将成员m_adaptee[Adaptee]的220V电压接口, 转换成Target类的20V电压接口 class Adapter : public Target { public : Adapter( ) :m_adaptee(new Adaptee) { //this->m_adaptee = new Adaptee( ); } ~Adapter( ) { if(this->m_adaptee != NULL) { delete this->m_adaptee; this->m_adaptee = NULL; } } void Request( ) // 我们需要的目标接口 { // 将成员m_adaptee[Adaptee]的220V电压接口, 转换成Target类的20V电压接口 this->m_adaptee->SpecialRequest( ); // 调用适配类的特殊(不符合)接口 } Adaptee *m_adaptee; }; int main(void) { Target *target = new Adapter( ); // 定义一个目标接口 target->Request( ); delete target; target = NULL; }
当客户在接口中定义了他期望的行为时,我们就可以应用适配器模式,提供一个实现该接口的类,并且扩展已有的类,通过创建子类来实现适配。
#include <iostream> // 目标接口信息 class Target { public : virtual void Request( ) // 希望获得的系统接口 { std::cout <<"Target::Request" <<std::endl; } }; // 需要适配的类, 内喊不符合要求的接口 class Adaptee { public : void SpecialRequest( ) { std::cout <<"Adaptee::SpecialRequest..." <<std::endl; } }; // 获取接口的适配器类, // 适配后的符合要求的接口 // 将目标类Adatee中不符合要求的接口, 转换为Target中的接口类型 class Adapter : public Target, Adaptee { public : void Request( ) { Adaptee::SpecialRequest( ); } }; int main() { Target *target = new Adapter( ); target->Request( ); delete target; target = NULL; return 0; }