设计模式-适配器模式

一、适配器模式核心概念解析

适配器模式是一种结构型设计模式 ,它的核心作用是:将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而无法一起工作的那些类可以协同工作。

你可以把它理解成生活中的「转接头」:比如你的手机充电线是 Type-C 接口,但插座只有 USB-A 口,这时候需要一个 Type-C 转 USB-A 的转接头(适配器),让充电线和插座能适配使用。

适配器模式的关键角色
  1. 目标接口(Target):客户期望使用的接口,是适配器最终要转换成的形式。
  2. 适配者(Adaptee):已存在的、接口不符合客户需求的类(需要被适配的类)。
  3. 适配器(Adapter):核心角色,实现目标接口,并内部持有适配者对象,将目标接口的调用转换为对适配者接口的调用。
适配器模式的两种实现方式
  • 类适配器:通过继承适配者类 + 实现目标接口来实现(依赖 C++ 的多继承),这个没啥用,尽量不用。
  • 对象适配器 :通过组合(持有适配者对象) + 实现目标接口来实现(更灵活,推荐使用)。

二、C++ 代码示例(对象适配器,推荐)

下面以「音频播放器」为例:假设现有一个只能播放 MP3 的播放器(适配者),但客户需要一个能播放「所有音频格式」的播放器(目标接口),我们通过适配器让 MP3 播放器适配成通用音频播放器。

完整代码
cpp 复制代码
#include <iostream>
#include <string>

// 1. 目标接口(Target):客户期望的通用音频播放器接口
class AudioPlayer {
public:
    virtual ~AudioPlayer() = default; // 虚析构,确保子类析构正常
    virtual void play(const std::string& audioType, const std::string& fileName) = 0;
};

// 2. 适配者(Adaptee):已存在的、接口不兼容的MP3播放器
class MP3Player {
public:
    // 适配者的原有接口(只能播放MP3)
    void playMP3(const std::string& fileName) {
        std::cout << "正在播放MP3文件: " << fileName << std::endl;
    }
};

// 3. 适配器(Adapter):将MP3Player适配成AudioPlayer接口
class AudioAdapter : public AudioPlayer {
private:
    MP3Player* mp3Player; // 组合适配者对象(对象适配器核心)
public:
    AudioAdapter() : mp3Player(new MP3Player()) {}
    
    ~AudioAdapter() {
        delete mp3Player; // 释放适配者对象
    }
    
    // 实现目标接口,内部转换为适配者的接口调用
    void play(const std::string& audioType, const std::string& fileName) override {
        // 只适配MP3格式(可扩展其他格式的适配)
        if (audioType == "mp3") {
            mp3Player->playMP3(fileName); // 转换调用
        } else {
            std::cout << "不支持的音频格式: " << audioType << std::endl;
        }
    }
};

// 客户端代码:使用目标接口,无需关心底层适配逻辑
int main() {
    // 创建适配器对象(对外暴露AudioPlayer接口)
    AudioPlayer* player = new AudioAdapter();
    
    // 客户端调用目标接口,适配者的接口被间接调用
    player->play("mp3", "周杰伦-晴天.mp3"); // 正常播放
    player->play("wav", "陈奕迅-孤勇者.wav"); // 不支持的格式
    
    delete player; // 释放资源
    return 0;
}
代码解释
  1. 目标接口(AudioPlayer) :定义了客户端期望的play方法,参数包含音频格式和文件名,是客户端直接调用的接口。
  2. 适配者(MP3Player) :已有类,只有playMP3方法,接口和目标接口不兼容(参数少、方法名不同)。
  3. 适配器(AudioAdapter) :
    • 继承AudioPlayer,实现目标接口;
    • 内部持有MP3Player对象(组合方式);
    • 重写play方法,将客户端的通用调用转换为对MP3Player::playMP3的调用。
  4. 客户端 :只依赖AudioPlayer接口,完全不用知道MP3Player的存在,实现了接口解耦。
运行结果
复制代码
正在播放MP3文件: 周杰伦-晴天.mp3
不支持的音频格式: wav

总结

  1. 核心作用:适配器模式解决「接口不兼容」问题,让原本无法协作的类可以一起工作,核心是「接口转换」。
  2. 实现方式 :
    • 推荐使用对象适配器(组合方式),耦合度低、灵活性高;
    • 类适配器(继承方式)仅适用于简单场景,依赖多继承,扩展性差。
  3. 应用场景:集成第三方库(接口固定)、复用已有旧代码(接口不匹配)、统一多个类的对外接口等。

类适配器模式的优缺点是什么?

除了对象适配器模式,还有哪些常见的适配器模式?

如何在实际项目中选择使用适配器模式?

相关推荐
高晶17 小时前
CANopen 在 BMS 系统中的 C 语言实战指南
设计模式·程序员
博风18 小时前
13、设计模式应用举例:工厂方法模式:创建药品对象
设计模式·工厂方法模式
代钦塔拉20 小时前
【C++/Qt 进阶】设计模式系列(5):适配器模式——给“不兼容的接口“贴一层翻译膜
c++·qt·设计模式
bigbread1 天前
策略模式 + 工厂方法模式在项目中的实战应用
设计模式
高晶1 天前
C 语言实现 BMS 系统中 SPI 通信协议实战指南
设计模式·程序员
代钦塔拉1 天前
【C++/Qt 进阶】设计模式系列(2):工厂模式——从游戏角色到披萨店
c++·算法·设计模式
高晶2 天前
2A3 单端甲类功放从零制作全攻略:电路设计、焊接调试到煲机维护一站式指南
前端·设计模式
代钦塔拉2 天前
【C++/Qt 进阶】设计模式系列(4):原型模式——用“克隆“代替“重新构造“
c++·qt·设计模式
yuehuaxin012 天前
LS8011C 快充协议芯片|SOT‑23‑6L 内置 431,PD3.2 SPR/PPS 适配器物料备选评估调试笔记
笔记·智能家居·适配器模式·智能硬件
博风2 天前
11、设计模式应用举例:迭代器模式:使用多个集合存储对象
设计模式·迭代器模式