一、适配器模式概念
适配器模式 (Adapter)是一种结构型设计模式, 它能使不兼容的对象能够相互合作。
适配器模式通过封装对象将复杂的转换过程隐藏于幕后。 被封装的对象甚至察觉不到适配器的存在。
适配器不仅可以转换不同格式的数据, 其还有助于采用不同接口的对象之间的合作。 它的运作方式如下:
- 适配器实现与其中一个现有对象兼容的接口。
- 现有对象可以使用该接口安全地调用适配器方法。
- 适配器方法被调用后将以另一个对象兼容的格式和顺序将请求传递给该对象。
适用场景
- 当你希望使用某个类, 但是其接口与其他代码不兼容时, 可以使用适配器类。
- 如果您需要复用这样一些类, 他们处于同一个继承体系, 并且他们又有了额外的一些共同的方法, 但是这些共同的方法不是所有在这一继承体系中的子类所具有的共性。
适配器设计模式的结构:
适配器实现了其中一个对象的接口, 并对另一个对象进行封装。
- 客户端 (Client) 是包含当前程序业务逻辑的类。
- 客户端接口 (Client Interface) 描述了其他类与客户端代码合作时必须遵循的协议。
- 服务 (Service) 中有一些功能类 (通常来自第三方或遗留系统)。 客户端与其接口不兼容, 因此无法直接调用其功能。
- 适配器 (Adapter) 是一个可以同时与客户端和服务交互的类: 它在实现客户端接口的同时封装了服务对象。 适配器接受客户端通过适配器接口发起的调用, 并将其转换为适用于被封装服务对象的调用。
- 客户端代码只需通过接口与适配器交互即可, 无需与具体的适配器类耦合。 因此, 你可以向程序中添加新类型的适配器而无需修改已有代码。 这在服务类的接口被更改或替换时很有用: 你无需修改客户端代码就可以创建新的适配器类。
代码如下:
问题:开发一款股票市场检测程序,会从不同来源下载XML格式的股票数据,然后向用户呈现出分析图表。但是,分析函数库只兼容JSON格式的数据。
解决方案:将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的类可以一起工作。即创建一个适配器,能够转换对象接口。
#include<iostream>
//Target:客户端需要的目标接口
class JasonInfo {
public:
virtual ~JasonInfo() {}
virtual std::string request() const {
return "Jason...";
}
};
//Adaptee:客户端不兼容的接口,需要转换为Target接口
class XmlInfo {
public:
std::string specialRequest() const {
return "special xml request...";
}
};
//Adaptor:适配器,就是把Adaptee包装起来,让他看上去像是Target
class XmlJasonAdaptor :public JasonInfo {
private:
XmlInfo* m_xmlInfo;
public:
XmlJasonAdaptor(XmlInfo* xmlInfo) :m_xmlInfo(xmlInfo) {}
virtual std::string request() const override {
std::string string1 = m_xmlInfo->specialRequest();
return "Iason<-XmlJasonAdaptor " + string1;
}
};
void clientCode(const JasonInfo* info) {
std::cout << "股票分析软件运行Jason:" << info->request() << std::endl;
std::cout << "-----------------------------------" << std::endl;
}
int main()
{
JasonInfo jasonInfo;
clientCode(&jasonInfo);
XmlInfo xmlInfo;
XmlJasonAdaptor xmlJasonAdaptor(&xmlInfo);
clientCode(&xmlJasonAdaptor);
return 0;
}