1.适配器(Adapter)模式动机
适配器在我们的生活中应用的场景有很多,例如网卡适配器,俗称网卡。网卡的作用是负责将电缆或双绞线中传输的串行数据转换为计算机内部处理的并行数据。又例如电源适配器,当前我们居民用电的电压为220V,而各大手机厂商生产的手机电压远远达不到如此。于是,手机电源适配器(充电器)出现了,它们负责将各类手机与220V电压之间进行兼容。
在软件系统中由于应用场景的变化,常常需要将一些现存对象引入到一个新场景中使用。但是,新场景要求的程序接口是现有对象所不能满足的。适配器模式的动机主要为了解决以下问题:如何应对这种迁移变化?如何既能够利用现有对象的良好实现,同时又能满足新的应用场景所要求的程序接口?
2.适配器(Adapter)模式定义
将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能在一起工作的那些类可以一起工作。在适配器模式中会设计一个适配器的包装类,适配器包装的对象称为适配者。适配器会根据客户的具体需求,将适配者已有的接口转换成另一个接口,从而可以使不兼容的类可以协同工作。适配器模式的UML类图如下所示:
3.适配器模式实战
假设A公司最近新收购了一家B公司,两家公司原先都有自己的员工管理系统,两个系统都可以获取自己公司员工的个人信息。现在B公司被A公司给收购了,A公司的领导要求使用自己公司的员工管理系统也可以查看B公司员工的信息。由于A、B两个公司获取员工信息的程序接口不同,此时适配器模式就是大显身手了。
#include <iostream> #include <string> using namespace std; // A公司员工管理系统 class ManageSystemA { public: virtual void getInfo() { cout << "获取A公司员工个人信息\n"; } }; // B公司员工管理系统 class ManageSystemB { public: virtual void getProfile() { cout << "获取B公司员工个人信息\n"; } }; // 适配器类Adapter class AdapterSystem: public ManageSystemA { public: AdapterSystem(ManageSystemB* pSysB): m_pSysB(pSysB){} virtual void getInfo() { m_pSysB->getProfile(); } private: ManageSystemB* m_pSysB; }; // 客户端程序 int main() { ManageSystemB* sysB = new ManageSystemB; // 创建适配器 ManageSystemA* sysA = new AdapterSystem(sysB); sysA->getInfo(); // 通过A公司的员工个人信息接口获取B公司员工个人信息 return 0; }
4.适配器模式总结
(1).适配器模式主要应用于希望复用一些现存的类,但接口又与复用场景要求不一致的情况,在遗留代码复用、类库迁移等方面非常有用。
(2).GOF 23定义了两种适配器模式实现结构:对象适配器和类适配器。但类适配器采用多继承的实现方式,一般不推荐使用。对象适配器采用对象组合的方式,更符合松耦合精神。