一、适配器模式
1.1、主要目的
是 兼容 ,将一个类的接口转换成期望的另一个接口,让两个类因接口不匹配,不能协同工作,变得可以一起工作
1.2、分类
适配器模式主要分为三种类型:
- 类适配器模式
- 通过继承目标类,实现适配接口,完成适配
- 看一些资料使用多重继承 来实现,虽然C++支持多重继承,但不推荐,容易产生经典的菱形继承问题。
- 对象适配器模式
- 通过组合目标类,实现适配接口,完成适配, 这是最常用、最推荐的实现方式
- 接口适配器模式
- 当一个接口定义了过多的方法,而某些类只需要实现接口的部分方法,而不需要实现接口的所有方法时,可以定义一个抽象类实现接口,并实现部分方法,其他类继承抽象类,实现需要的方法即可。
二、为什么需要适配器模式
以当前实际背景为例,现在国内大部分软件,操作系统,数据库等都在进行国产化迭代更新,如果不采用适配器模式,直接重构代码,将会耗费大量人力物力,且重构过程中,可能会出现不可预料的问题,导致项目延期,甚至失败,所以,适配器模式应运而生,通过适配器模式,可以快速兼容现有系统,降低重构成本,提高开发效率。
其他应用场景:
- 集成遗留系统:新旧系统集成时,接口不兼容
- 第三方库适配:使用不兼容接口的第三方库
- 接口标准化:统一多个类似但接口不同的组件
三、UML图
3.1、类适配器模式

3.2、对象适配器模式

3.3、接口适配器模式

四、实际应用
4.1、类适配器模式
4.1.1、场景
以PostgreSQL数据库 为例,PostgreSQL数据库在适配国产化过程中,需要兼容Oracle数据库 ,而Oracle数据库的接口与PostgreSQL数据库的接口不一致,所以,需要使用适配器模式,将Oracle数据库的接口转换为PostgreSQL数据库的接口。
4.1.2、UNL图

4.1.3、实现
目标接口
cpp
// PostgreSQL接口(目标接口)
class PostgreSQLInterface
{
public:
virtual ~PostgreSQLInterface() = default;
virtual void connect() = 0;
virtual void executeQuery(const std::string& query) = 0;
virtual void close() = 0;
};
被适配者
cpp
// Oracle数据库(被适配者)
class OracleDatabase
{
public:
void oracleConnect()
{
std::cout << "Oracle:连接到数据库\n";
}
void oracleQuery(const std::string& query)
{
std::cout << "Oracle:执行查询: " << query << std::endl;
}
void oracleClose()
{
std::cout << "Oracle: 关闭数据库连接" << std::endl;
}
};
类适配器
cpp
class OracleToPostgreSQLAdapter : public PostgreSQLInterface, private OracleDatabase
{
public:
void connect()override
{
std::cout << "适配器:调用oracle连接方法\n";
OracleDatabase::oracleConnect();
}
void executeQuery(const std::string& query)override
{
std::cout << "适配器:转换并执行Oracle查询\n";
std::string convertedQuery = this->convertQueryToOracleSyntax(query);
OracleDatabase::oracleQuery(convertedQuery);
}
void close()override
{
std::cout << "OracleToPostgreSQLAdapter call closed.\n";
OracleDatabase::oracleClose();
}
private:
std::string convertQueryToOracleSyntax(const std::string& postgreSQLQuery)
{
// 简单化查询语句的转换
if (postgreSQLQuery.find("LIMIT") != std::string::npos) {
return "SELECT * FROM (SELECT t.*, ROWNUM rnum FROM (" +
postgreSQLQuery.substr(0, postgreSQLQuery.find("LIMIT")) +
") t WHERE ROWNUM <= 100) WHERE rnum >= 1";
}
else {
return postgreSQLQuery;
}
}
};
测试代码
cpp
void test1()
{
std::cout << "================类适配器模式================\n";
std::unique_ptr<PostgreSQLInterface> db = std::make_unique<OracleToPostgreSQLAdapter>();
// 使用统一的PostgreSQL 接口
db->connect();
db->executeQuery("SELECT * FROM users");
db->close();
}

4.2、对象适配器模式
4.2.1、场景
一个系统原本使用文件存储,现在需要切换到云存储服务,但云存储服务的API与现有文件系统接口不兼容,所以需要使用适配器模式,将云存储服务的API转换为文件系统的API。
4.2.2、UNL图

4.2.3、实现
目标接口
cpp
// 文件系统接口(目标接口)
class FileSystem
{
public:
virtual ~FileSystem() = default;
virtual std::string readFile(const std::string& filename) = 0;
virtual void writeFile(const std::string& filename, const std::string& content) = 0;
virtual void deleteFile(const std::string& filename) = 0;
};
被适配者
cpp
// 云存储服务(被适配者)
class CloudStorage
{
private:
std::map<std::string, std::string> storage;
public:
std::string getObject(const std::string& key)
{
std::cout << "云存储:获取对象 " << key << std::endl;
if (storage.find(key) != storage.end()) {
return storage[key];
}
return "";
}
void putObject(const std::string& key, const std::string& data)
{
std::cout << "云存储:存储对象 " << key << std::endl;
storage[key] = data;
}
void removeObject(const std::string& key)
{
std::cout << "云存储:删除对象 " << key << std::endl;
storage.erase(key);
}
};
对象适配器
cpp
class CloudStorageAdapter :public FileSystem
{
private:
std::unique_ptr<CloudStorage> cloudStorage;
public:
CloudStorageAdapter()
:cloudStorage{ std::make_unique<CloudStorage>() }
{
}
std::string readFile(const std::string& filename)override
{
std::cout << "适配器:将文件读取转换为云存储获取对象\n";
std::string objectKey = this->convertFilePathToObjectKey(filename);
return cloudStorage->getObject(objectKey);
}
void writeFile(const std::string& filename, const std::string& content) override
{
std::cout << "适配器: 将文件写入转换为云存储存储对象" << std::endl;
std::string objectKey = this->convertFilePathToObjectKey(filename);
cloudStorage->putObject(objectKey, content);
}
void deleteFile(const std::string& filename) override
{
std::cout << "适配器: 将文件删除转换为云存储删除对象" << std::endl;
std::string objectKey = this->convertFilePathToObjectKey(filename);
cloudStorage->removeObject(objectKey);
}
private:
std::string convertFilePathToObjectKey(const std::string& filePath)
{
return "/home/user/" + filePath;
}
};
测试代码
cpp
void test2()
{
std::cout << "======================对象适配器模式====================\n";
std::unique_ptr<FileSystem> fs = std::make_unique<CloudStorageAdapter>();
fs->writeFile("document/new.txt", "aabbccdd");
std::string content = fs->readFile("document/new.txt");
std::cout << "content: " << content << std::endl;
fs->deleteFile("document/new.txt");
}

4.3、接口适配器模式
4.3.1、场景
一个类定义了许多方法,但只需要其中的几个方法。为避免实现类需要实现所有方法,可以使用接口适配器模式,创建一个适配器类,只实现需要的方法。
4.3.2、UNL图

4.3.3、实现
定义过多的方法
cpp
class DataChangeListener
{
public:
virtual ~DataChangeListener() = default;
// 数据变化事件
virtual void onDataAdded(const std::string& data) = 0;
virtual void onDataUpdated(const std::string& data) = 0;
virtual void onDataDeleted(const std::string& data) = 0;
virtual void onDataMoved(const std::string& from, const std::string& to) = 0;
virtual void onDataCopied(const std::string& src, const std::string& dest) = 0;
virtual void onDataRenamed(const std::string& oldName, const std::string& newName) = 0;
// 系统事件
virtual void onError(const std::string& error) = 0;
virtual void onWarning(const std::string& warning) = 0;
virtual void onInfo(const std::string& info) = 0;
// 状态事件
virtual void onStart() = 0;
virtual void onStop() = 0;
virtual void onPause() = 0;
virtual void onResume() = 0;
};
定义一个适配器类,为所有方法提供空实现
cpp
class DataChangeAdapter : public DataChangeListener
{
public:
// 数据变化事件 - 默认空实现
void onDataAdded(const std::string& data) override {}
void onDataUpdated(const std::string& data) override {}
void onDataDeleted(const std::string& data) override {}
void onDataMoved(const std::string& from, const std::string& to) override {}
void onDataCopied(const std::string& src, const std::string& dest) override {}
void onDataRenamed(const std::string& oldName, const std::string& newName) override {}
// 系统事件 - 默认空实现
void onError(const std::string& error) override {}
void onWarning(const std::string& warning) override {}
void onInfo(const std::string& info) override {}
// 状态事件 - 默认空实现
void onStart() override {}
void onStop() override {}
void onPause() override {}
void onResume() override {}
};
具体实现类1
cpp
// 具体实现1:只关心数据添加和删除
class SimpleDataLogger : public DataChangeAdapter
{
public:
void onDataAdded(const std::string& data) override {
std::cout << "[日志] 数据添加: " << data << std::endl;
}
void onDataDeleted(const std::string& data) override {
std::cout << "[日志] 数据删除: " << data << std::endl;
}
void onError(const std::string& error) override {
std::cout << "[日志] 错误: " << error << std::endl;
}
};
具体实现类2
cpp
// 具体实现2:只关心数据更新
class DataUpdateMonitor : public DataChangeAdapter
{
public:
void onDataUpdated(const std::string& data) override {
std::cout << "[监控] 数据更新: " << data << std::endl;
// 可以触发相关业务逻辑
notifyRelatedSystems(data);
}
void onStart() override {
std::cout << "[监控] 监控器启动" << std::endl;
}
void onStop() override {
std::cout << "[监控] 监控器停止" << std::endl;
}
private:
void notifyRelatedSystems(const std::string& data) {
std::cout << "[监控] 通知相关系统: " << data << std::endl;
}
};
cpp
// 数据管理器---方便于管理多个实现类
class DataManager {
private:
std::shared_ptr<DataChangeListener> listener;
public:
void setListener(std::shared_ptr<DataChangeListener> listener) {
this->listener = listener;
}
void addData(const std::string& data) {
std::cout << "数据管理器: 添加数据 '" << data << "'" << std::endl;
if (listener) listener->onDataAdded(data);
}
void updateData(const std::string& data) {
std::cout << "数据管理器: 更新数据 '" << data << "'" << std::endl;
if (listener) listener->onDataUpdated(data);
}
void deleteData(const std::string& data) {
std::cout << "数据管理器: 删除数据 '" << data << "'" << std::endl;
if (listener) listener->onDataDeleted(data);
}
void start() {
std::cout << "数据管理器: 启动" << std::endl;
if (listener) listener->onStart();
}
void stop() {
std::cout << "数据管理器: 停止" << std::endl;
if (listener) listener->onStop();
}
};
测试代码
cpp
void test3()
{
std::cout << "============== 接口适配器模式 ============" << std::endl;
DataManager manager;
std::cout << "\n1. 使用简单日志监听器:" << std::endl;
auto simpleLogger = std::make_shared<SimpleDataLogger>();
manager.setListener(simpleLogger);
manager.start();
manager.addData("测试数据1");
manager.deleteData("测试数据1");
manager.stop();
std::cout << "\n2. 使用数据更新监控器:" << std::endl;
auto updateMonitor = std::make_shared<DataUpdateMonitor>();
manager.setListener(updateMonitor);
manager.start();
manager.updateData("测试数据2");
manager.stop();
}

五、总结
5.1、优点
-
单一职责原则:将接口转换代码从业务逻辑中分离
-
开闭原则:可以在不修改现有代码的情况下引入新的适配器
-
提高代码复用性:可以复用已有的类
-
提高灵活性:可以动态切换不同的适配器
5.2、缺点
-
代码复杂度增加:需要增加新的类和接口
-
增加系统理解难度:需要理解适配器模式的工作原理
-
增加系统运行时开销:需要创建新的对象和接口
5.3、三种适配器进行比较
| 类适配器 | 对象适配器 | 接口适配器 | |
|---|---|---|---|
| 实现方式 | 多重继承 | 组合 | 继承抽象类 |
| 灵活性 | 较低 | 较高 | 中等 |
| 耦合度 | 较高 | 较低 | 中等 |
| 推荐度 | 不推荐 | 推荐 | 视情况而定 |
| 适用场景 | 适配器需要同时是目标和被适配者 | 需要适配多个对象 | 接口方法过多,只使用部分 |
5.4、提示
实际项目中,遇到的往往是有实现的抽象类,而不是纯虚接口;此时,可以使用对象适配器模式 ,将抽象类作为适配器,将具体实现类作为被适配者,通过组合的方式实现适配;还可以直接继承;如果时间充裕,可以考虑重构代码,考虑之前的设计是否合理。