适配器模式是什么?
适配器模式将一个类的接口转换成客户端期望的另一个接口,消除由于接口不兼容而导致的类无法一起工作的问题。举个例子解释:一个笔记本电脑不支持插入存储卡,那有什么办法可以在笔记本上读取存储卡的数据呢,这是你会想到使用读卡器。读卡器就是作为存储卡和笔记本之间的适配器。将存储卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来访问存储卡。相比于这个例子,我们在程序开发中,可能笔记本电脑的接口已经是通用接口,无法改变,二存储卡的接口也无法改变,此时我们还要实现笔记本电脑去访问存储卡,而且可能还需要访问很多不同的存储卡,每种存储的接口都不一样,这是我们需要开发的就是笔记本电脑和存储卡之间的适配器
应用场景
- 需要使用现有类,但其接口不符合系统需求
- 希望创建一个可复用的类,与多个不相关的类(包括未来可能引入的类)一起工作,这些类可能没有统一的接口
- 通过接口转换将一个类集成到另一个类系中
定义方式
- 目标接口(Target):定义客户需要的接口
- 适配者类(Adaptee):定义一个已经存在的接口,这个接口需要适配
- 适配器类(Adapter):实现目标接口,并通过组合或继承的方式调用适配者类中的方法,从而实现接口
实现方式
类适配器模式
#include <iostream>
class Source {
public:
void method1() {
std::cout << "This is original method..." << std::endl;
}
};
class Targetable {
public:
virtual void method1() = 0;
virtual void method2() = 0;
virtual ~Targetable() {}
};
class Adapter : public Source, public Targetable {
public:
void method2() override {
std::cout << "This is the targetable method..." << std::endl;
}
};
int main() {
Targetable* target = new Adapter();
target->method1();
target->method2();
delete target;
return 0;
}
对象适配器模式
#include <iostream>
#include <string>
using namespace std;
// 对象的适配器模式
// Source 类的定义
class Source {
public:
void method1() {
cout << "This is original method..." << endl;
}
};
// Targetable 接口的定义
class Targetable {
public:
virtual void method1() = 0; // 与原类中的方法相同
virtual void method2() = 0; // 新类的方法
};
// Wrapper 类实现了 Targetable 接口
class Wrapper : public Targetable {
private:
Source* source; // 持有 Source 类的实例
public:
Wrapper(Source* s) : source(s) {}
void method1() override {
source->method1();
}
void method2() override {
cout << "This is the targetable method..." << endl;
}
};
int main() {
Source* source = new Source();
Targetable* targetable = new Wrapper(source);
targetable->method1();
targetable->method2();
delete source;
delete targetable;
return 0;
}
接口的适配器模式
// 接口的适配器模式
#include <iostream>
using namespace std;
// 定义端口接口,提供通信服务
class Port {
public:
virtual void SSH() = 0;
virtual void NET() = 0;
virtual void Tomcat() = 0;
virtual void MySQL() = 0;
};
// 定义抽象类实现端口接口,但是什么事情都不做
class Wrapper : public Port {
public:
void SSH() override {}
void NET() override {}
void Tomcat() override {}
void MySQL() override {}
};
// 提供聊天服务,需要网络功能
class Chat : public Wrapper {
public:
void NET() override {
cout << "Hello World..." << endl;
}
};
// 网站服务器,需要Tomcat容器,MySQL数据库,网络服务,远程服务
class Server : public Wrapper {
public:
void SSH() override {
cout << "Connect success..." << endl;
}
void NET() override {
cout << "WWW..." << endl;
}
void Tomcat() override {
cout << "Tomcat is running..." << endl;
}
void MySQL() override {
cout << "MySQL is running..." << endl;
}
};
int main() {
Port* chatPort = new Chat();
Port* serverPort = new Server();
// 聊天服务
chatPort->NET();
// 服务器
serverPort->SSH();
serverPort->NET();
serverPort->Tomcat();
serverPort->MySQL();
delete chatPort;
delete serverPort;
return 0;
}
适配器模式通常是通过创建一个新类来实现。这个新类“包裹”了原来的类,同时实现了目标接口(需要的方式)。这样,外部代码就可以通过适配器类来使用原来的类,而不需要关心接口的不同。