适配器模式(Adapter Pattern)
定义
适配器模式是一种结构性设计模式,通过创建一个中间适配层,使得接口不兼容的类可以一起工作。
核心思想
适配器模式的目的是:
- 接口转换:将一个类的接口转换成客户期望的另一个接口。
- 兼容性增强:让原本由于接口不兼容而无法工作的类能够协同工作。
应用场景
- 使用第三方库或插件时,如果其接口与现有系统接口不兼容,可以使用适配器模式。
- 系统中有多个接口需要协同工作,但接口规范不统一。
- 代码重构代价较大时,可以使用适配器实现接口的兼容。
适配器模式结构
-
目标接口(Target):
- 定义客户端期望使用的接口(例如:
VGA
)。
- 定义客户端期望使用的接口(例如:
-
适配者类(Adaptee):
- 具有不兼容接口的类(例如:
HDMI
)。
- 具有不兼容接口的类(例如:
-
适配器类(Adapter):
- 实现目标接口,并包装适配者类,将目标接口的调用委托给适配者类完成。
代码实现思路
以电脑投影仪接口为例:
-
目标接口(VGA):
- 定义传统接口,电脑通过它输出视频信号。
-
适配者类(HDMI):
- 定义新的接口,支持高清信号传输。
-
适配器类(VGA to HDMI Adapter):
- 将电脑的 VGA 信号转换为 HDMI 信号,使老接口与新接口兼容。
完整代码实现
#include <iostream>
#include <string>// 目标接口:VGA
class VGA {
public:virtual void play() = 0; // 抽象方法virtual ~VGA() = default;
};// 适配者接口:HDMI
class HDMI {
public:virtual void play() = 0; // 抽象方法virtual ~HDMI() = default;
};// 具体实现:支持 VGA 的投影仪
class TV_VGA : public VGA {
public:void play() override {std::cout << "Using VGA to connect to the projector for video playback.\n";}
};// 具体实现:支持 HDMI 的投影仪
class TV_HDMI : public HDMI {
public:void play() override {std::cout << "Using HDMI to connect to the projector for video playback.\n";}
};// 适配器类:VGA 转 HDMI
class VGAtoHDMIAdapter : public VGA {
private:HDMI* hdmi; // 持有 HDMI 的引用
public:VGAtoHDMIAdapter(HDMI* newHdmi) : hdmi(newHdmi) {}void play() override {std::cout << "Adapter converting VGA to HDMI...\n";hdmi->play(); // 调用 HDMI 的 play 方法}
};// 客户端代码:电脑类
class Computer {
public:void playVideo(VGA* vgaDevice) {vgaDevice->play();}
};// 主函数
int main() {// 使用支持 VGA 的投影仪Computer computer;TV_VGA vgaProjector;computer.playVideo(&vgaProjector);// 使用支持 HDMI 的投影仪,需要适配器TV_HDMI hdmiProjector;VGAtoHDMIAdapter adapter(&hdmiProjector);computer.playVideo(&adapter);return 0;
}
运行结果
Using VGA to connect to the projector for video playback.
Adapter converting VGA to HDMI...
Using HDMI to connect to the projector for video playback.
代码解析
-
接口定义:
VGA
定义了老的 VGA 接口。HDMI
定义了新的 HDMI 接口。
-
适配器逻辑:
VGAtoHDMIAdapter
实现了VGA
接口,同时内部封装了HDMI
对象,将VGA
的操作转换为HDMI
的操作。
-
客户端使用:
- 电脑(
Computer
)只知道如何与VGA
设备交互,不需要关心设备是否是HDMI
,适配器在其中完成了兼容处理。
- 电脑(
适配器模式的优缺点
优点:
- 提高类的兼容性:让原本接口不兼容的类能够协同工作。
- 遵循单一职责原则:适配器负责接口转换,客户端和适配者类都无需改变。
- 扩展性强:可以轻松增加新的适配器类,以支持更多的接口。
缺点:
- 额外的适配成本:需要额外创建适配器类,会增加一定的代码量。
- 系统复杂度增加:如果过多使用适配器,可能会让系统结构变得复杂。
适配器模式的两种实现方式
-
对象适配器(本例):
- 通过组合的方式,在适配器中持有适配者类的引用。
- 优点:灵活性高,可以适配多个适配者。
-
类适配器:
- 通过多重继承,使适配器同时继承目标接口和适配者类。
- 缺点:需要支持多继承,灵活性较低。
适配器模式与其他模式的区别
模式 | 用途 | 实现方式 |
---|---|---|
适配器模式 | 接口转换,解决接口不兼容问题 | 增加适配器类 |
装饰器模式 | 动态增强对象功能 | 包装对象,递归调用 |
代理模式 | 控制对象访问,保护对象或延迟初始化 | 持有对象引用,控制访问逻辑 |
总结
- 适配器模式的核心功能:解决接口不兼容的问题,使现有类和新类可以一起工作。
- 应用场景:在整合第三方库或插件时,常用于解决接口不一致的问题。
- 实践建议:尽量避免频繁使用适配器,而是优先考虑设计统一的接口。如果不能更改现有代码,可以使用适配器作为临时解决方案。