设计模式:适配器模式(Adapter Pattern)

设计模式|适配器模式(Adapter Pattern) 适配器模式(Adapter Pattern)是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一个接口。这种模式通常用于解决两个已有接口之间不兼容的情况。适配器模式使得不兼容的接口能够协同工作,而无需修改已有的代码。这对于集成已有代码库或者第三方组件时非常有用,因为它可以帮助在不破坏现有接口的情况下实现必要的功能补充。 阅读详情

一、适配器模式简介

适配器模式是一种结构型设计模式, 它能使接口不兼容的对象能够相互合作。
它的主要作用是:

  • 将一个类的接口转换成客户端希望的另一个接口。
  • 让原本接口不兼容的类能够一起工作。

类似于现实中的“插头适配器”:电源插座是两孔的,但你的设备插头是三孔的,需要一个转换头来兼容。

适配器模式的角色:

  1. 目标接口(Target):客户端期望使用的接口。
  2. 适配者(Adaptee):已有的接口或类,但接口格式不符合目标接口。
  3. 适配器(Adapter):中间的桥梁,把 Adaptee 的接口转成 Target 的接口。

适配器模式的实现方式:

  1. 类适配器(使用继承):通过多继承来适配(C++ 支持)。缺点:受限于 C++ 单继承/多继承的复杂性。
  2. 对象适配器(使用组合):通过持有一个 Adaptee 对象,在 Adapter 中转发调用(推荐)。

在这里插入图片描述

二、具体实例分析

问题:
假如你正在开发一款股票市场监测程序, 它会从不同来源下载 XML 格式的股票数据, 然后向用户呈现出美观的图表。

在开发过程中, 你决定在程序中整合一个第三方智能分析函数库。 但是遇到了一个问题, 那就是分析函数库只兼容 JSON 格式的数据。 无法 “直接” 使用分析函数库, 因为它所需的输入数据格式与你的程序不兼容。

在这里插入图片描述
可以修改程序库来支持 XML。 但是, 这可能需要修改部分依赖该程序库的现有代码。 甚至还有更糟糕的情况, 你可能根本没有程序库的源代码, 从而无法对其进行修改。

解决方案:
你可以创建一个适配器。 这是一个特殊的对象, 能够转换对象接口, 使其能与其他对象进行交互。

适配器模式通过封装对象将复杂的转换过程隐藏于幕后。 被封装的对象甚至察觉不到适配器的存在。 例如, 你可以使用一个将所有数据转换为英制单位 (如英尺和英里) 的适配器封装运行于米和千米单位制中的对象。

适配器不仅可以转换不同格式的数据, 其还有助于采用不同接口的对象之间的合作。 它的运作方式如下:

  1. 适配器实现与其中一个现有对象兼容的接口。
  2. 现有对象可以使用该接口安全地调用适配器方法。
  3. 适配器方法被调用后将以另一个对象兼容的格式和顺序将请求传递给该对象。

有时你甚至可以创建一个双向适配器来实现双向转换调用。

在这里插入图片描述
让我们回到股票市场程序。 为了解决数据格式不兼容的问题, 你可以为分析函数库中的每个类创建将 XML 转换为 JSON 格式的适配器, 然后让客户端仅通过这些适配器来与函数库进行交流。 当某个适配器被调用时, 它会将传入的 XML 数据转换为 JSON 结构, 并将其传递给被封装分析对象的相应方法。

适配器模式结构:
实现时使用了构成原则: 适配器实现了其中一个对象的接口, 并对另一个对象进行封装。 所有流行的编程语言都可以实现适配器。
在这里插入图片描述
说明:

  1. Client Interface(Target:目标接口):客户端期望使用的接口。
  2. Service(Adaptee:适配者):已有的类,功能正确,但接口与 Target 不兼容。
  3. Adapter(适配器):作为桥梁,把 Adaptee 的 serviceMethod(specialData) 转换为 Target 的 method(data)。一般通过 组合(持有一个 Adaptee 对象)来实现。

示例代码:
需求:客户端需要统一的 MediaPlayer 接口来播放音频,但现有的 AdvancedMediaPlayer 只支持 MP4 和 VLC 格式。用适配器模式来让 AdvancedMediaPlayer 适配到 MediaPlayer。

#include <iostream>
#include <memory>
using namespace std;

// 目标接口 (客户端期望使用的接口)
class MediaPlayer {
public:
    virtual void play(const string& filename) = 0;
    virtual ~MediaPlayer() = default;
};

// 适配者 (已有的接口,但不兼容)
class AdvancedMediaPlayer {
public:
    void playVlc(const string& filename) {
        cout << "Playing vlc file: " << filename << endl;
    }
    void playMp4(const string& filename) {
        cout << "Playing mp4 file: " << filename << endl;
    }
};

// 适配器 (桥梁)
class MediaAdapter : public MediaPlayer {
public:
    MediaAdapter(const string& type) {
        player = make_unique<AdvancedMediaPlayer>();
        format = type;
    }

    void play(const string& filename) override {
        if (format == "vlc")
            player->playVlc(filename);
        else if (format == "mp4")
            player->playMp4(filename);
        else
            cout << "Invalid format: " << format << endl;
    }

private:
    unique_ptr<AdvancedMediaPlayer> player;
    string format;
};

// 客户端使用
class AudioPlayer : public MediaPlayer {
public:
    void play(const string& filename) override {
        // 简单判断扩展名
        if (filename.find(".mp3") != string::npos) {
            cout << "Playing mp3 file: " << filename << endl;
        } else if (filename.find(".mp4") != string::npos) {
            adapter = make_unique<MediaAdapter>("mp4");
            adapter->play(filename);
        } else if (filename.find(".vlc") != string::npos) {
            adapter = make_unique<MediaAdapter>("vlc");
            adapter->play(filename);
        } else {
            cout << "Unsupported format: " << filename << endl;
        }
    }

private:
    unique_ptr<MediaAdapter> adapter;
};

int main() {
    unique_ptr<MediaPlayer> player = make_unique<AudioPlayer>();

    player->play("song.mp3");
    player->play("movie.mp4");
    player->play("video.vlc");
    player->play("unknown.avi");

    return 0;
}

类适配器(使用继承) 结构图:
这一实现使用了继承机制: 适配器同时继承两个对象的接口。 请注意, 这种方式仅能在支持多重继承的编程语言中实现, 例如 C++。
在这里插入图片描述
示例代码:

#include <QCoreApplication>
#include <QDebug>

// 目标接口(客户端需要的接口)
class Printer {
public:
    virtual void print(const QString &text) = 0;
    virtual ~Printer() {}
};

// 适配者(已有的老接口)
class OldPrinter {
public:
    void oldPrint(const QByteArray &data) {
        qDebug() << "OldPrinter printing:" << data;
    }
};

// 类适配器(继承 Target 和 Adaptee)
class ClassAdapter : public Printer, public OldPrinter {
public:
    void print(const QString &text) override {
        QByteArray data = text.toUtf8();
        oldPrint(data);  // 调用旧接口
    }
};

// 使用示例
void testClassAdapter() {
    Printer *printer = new ClassAdapter();
    printer->print("Hello Class Adapter!");
    delete printer;
}

三、示例代码

场景说明:
假设我们有一个 老打印机类 OldPrinter,只能打印 QByteArray,而新的客户端需要一个接口 Printer 能打印 QString。我们用适配器把旧接口适配给新接口。

① 目标接口(Target)

class Printer {
public:
    virtual void print(const QString &text) = 0;
    virtual ~Printer() {}
};

② 被适配类(Adaptee)

class OldPrinter {
public:
    void oldPrint(const QByteArray &data) {
        qDebug() << "OldPrinter printing:" << data;
    }
};

③ 适配器(Adapter,对象适配器)

class PrinterAdapter : public Printer {
public:
    PrinterAdapter(OldPrinter *oldPrinter) : m_oldPrinter(oldPrinter) {}

    void print(const QString &text) override {
        // 将 QString 转成 QByteArray,调用旧打印机
        QByteArray data = text.toUtf8();
        m_oldPrinter->oldPrint(data);
    }

private:
    OldPrinter *m_oldPrinter;  // 组合关系
};

④ 客户端使用

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    OldPrinter oldPrinter;

    Printer *printer = new PrinterAdapter(&oldPrinter);
    printer->print("Hello Adapter Pattern!");
    
    delete printer;
    return a.exec();
}

分析:

  1. Printer 是客户端期望的接口(Target)。
  2. OldPrinter 是已有的类(Adaptee),接口不兼容。
  3. PrinterAdapter 是适配器(Adapter),组合了 OldPrinter 对象,将 QString 转为 QByteArray 并调用旧接口。
  4. 客户端只依赖 Printer,无需知道底层 OldPrinter 的存在。
Golang 设计模式系列4: 适配器模式(Adapter design pattern) 适配器模式(Adapter Pattern) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。 适配器模式包含如下角色: Target:目标抽象类 Adapter:适配器类 Adaptee:适配者类 Client:客户类 实现 Target:目标抽象类 type L... 阅读详情

相关推荐

(32)C#设计模式——适配器模式(Adapter Pattern)

引言 在实际的开发过程中,由于应用环境的变化,我们需要的实现在新环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象。如何在新环境中调用“现存的对象”呢?采用适配器模式可以解决。适配器模式使得新环境中不需要去重复实现已经存在了的实现,而很好的把现有的对象(指原来环境中的现有对象)加入到新环境中来使用。 详细介绍 定义:把一个类的接口变换成客户端所期待的另一种接口,从而使得原本接口不匹...

编程菜鸟0604的博客 2020

适配器模式(Adapter Pattern)

一、定义 适配器模式(Adapter Pattern):结构型模式之一,将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。 二、UML类图 三、角色职责 目标角色(Target):该角色定义把其他类转换为何种接口,也就是我们的期望接口。 源角色(Adaptee):你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象。 适配器角色(Adapter):适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器

奶油芝士蘑菇汤的博客 2万+

银河麒麟V11 + KVM/QEMU + GT 710 GPU直通 Win10 完整操作流程文档

宿主机:RTX 5080专门运行ollama大模型服务,通过SSH/VNC远程管理Win10虚拟机:GT 710直通,物理键盘专属,通过物理显示器处理视频应用硬件隔离:两个系统完全隔离,互不干扰,性能最大化两种不同的直通方式直通方式 配置方法 设备在宿主机的状态 典型应用场景PCIe设备直通 vfio-pci.ids=10de:128b,10de:0e0f 设备完全从宿主机消失,被vfio-pci驱动接管 GPU、网卡、NVMe硬盘。

weixin_45285654的博客 1151

设计模式第9讲——适配器模式(Adapter)

适配器模式是一种结构型设计模式,它允许将不兼容的对象转换成可兼容的接口。主要目的是解决在不改变现有代码的情况下,使不兼容的接口之间能够正常工作,通过创建一个中间转换的适配器来将一个对象转换成我们所需要的接口。当我们去国外旅游时,我们可能只会汉语,而当地人只会英语,那么这个时候就需要一个翻译员(翻译软件)来帮助我们。这就类似于适配器模式,通过一个适配器将一个不兼容的接口转成另外一个接口。下面以翻译为例,介绍一下类、接口、对象适配器。

让~学习~成为一种习惯(橡 皮 人の技术博客) 3万+

手把手教你用FFmpeg实操:H.264转码、AVS2编码与H.265/HEVC参数调优避坑指南

本文详细解析了使用FFmpeg进行H.264转码、AVS2编码与H.265/HEVC参数调优的实战技巧。通过具体命令示例和参数详解,帮助开发者避开常见编码陷阱,提升视频处理效率和质量,特别适合音视频开发者和内容创作者参考。

weixin_30889885的博客 482

Oracle VM VirtualBox虚拟机网络配置与静态IP设置实战

本文详细讲解了Oracle VM VirtualBox虚拟机的网络配置,特别是如何设置静态IP以实现稳定访问。文章对比了NAT、桥接、仅主机等网络模式,并提供了从VirtualBox管理界面到Linux系统内部的完整配置步骤,帮助用户解决IP变动问题,构建可靠的本地开发测试环境。

weixin_28365523的博客 510

设计模式之适配器模式详解

设计模式之适配器模式详解 文章目录设计模式之适配器模式详解一、什么是适配器模式二、适配器模式的角色组成三、适配器模式应用场景四、适配器模式--类适配器示例五、适配器模式--对象适配器示例六、适配器模式--接口适配器示例七、适配器模式优缺点 一、什么是适配器模式 适配器模式(Adapter Pattern) 也称为变压器模式 ,它的功能是将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配而导致无法在一起工作的两个类能够一起工作,属于结构型设计模式。适配器模式其实起着转化、委托的作用,将一种接

weixin_45538589的博客 4192

window系统 dlib库安装

1. 安装visual studio 1.1. 安装vs2017或以上版本 1.2. 我们需要安装使用C++的桌面开发,且必须选上用于Cmake的Visual C++工具 1.3. 安装完成后,将D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin 添加到环境变量PATH中 2 下载cmake文件,并添加环境变量 2.1 在c

@bangbang的博客 815

设计模式-适配器模式(Adapter)

适配器模式(Adapter Pattern)是一种结构型设计模式,它主要用于解决两个不兼容的接口之间的问题。这种模式通过结合两个独立接口的功能,使原本不能一起工作的那些类可以一起工作。适配器模式涉及到一个单一的类,这个类负责将独立的或不兼容的接口功能整合到一起。举个例子,读卡器就是作为内存卡和笔记本之间的适配器。我们先把内存卡插入读卡器,再把读卡器插入笔记本,然后就可以通过笔记本来读取内存卡的内容了。

miaoyl的博客 5712

先进封装技术 Part03---重布线层(RDL)的科普

RDL是一种在芯片封装过程中用于重新分布电气连接的技术。它通过在芯片表面或中介层上形成额外的布线层,重新分配芯片的I/O(输入/输出)位置,以适应不同的封装需求和提高电气连接的灵活性。

阿拉伯梳子的专栏 4697

RT-Thread NANO V4.1.1 在Cortex-M0上移植踩坑记:解决内存分配宏导致的线程创建失败

本文详细记录了RT-Thread NANO V4.1.1在Cortex-M0平台移植过程中遇到的内存分配宏配置问题,导致线程创建失败的解决方案。通过分析内存管理算法宏定义,将RT_USING_SMALL_MEM替换为RT_USING_SMALL_MEM_AS_HEAP,成功解决了线程创建问题,为开发者提供了实用的移植经验。

weixin_29189373的博客 306

23种设计模式:适配器模式(最强解析!!!)

适配器模式是23种设计模式之一。 适配器模式作用 适配器模式的作用,在于将一个类的接口变换为客户端所期待的另一种接口,使得原本因为接口不匹配而无法一起工作的两个类能在一起工作。 也就是说,适配器模式解决的是接口兼容性问题。 适配器模式实现方式 适配器模式依据实现方式的不同,可以划分为3种:类适配器、对象适配器和接口适配器。 (一)类适配器 类适配器类图如下: 类适配器主要由三部分构成: Target:目标角色,也即被转换后的接口; Adaptee:源角色,需要被转换的接口; Ad.

进击的Coder*的博客 4715

【ComfyUI】SDXL + 单LoRA 房屋平面图渲染装修

本文介绍了一种基于ComfyUI的室内平面设计图自动生成效果图的工作流。该流程通过导入房屋平面图,结合SDXL室内设计模型与北欧风格LoRA模块,快速生成多房间效果展示。工作流包含图像输入、文本处理、模型加载和图像生成等环节,支持风格化渲染和细节补充,适用于建筑设计、家装展示、房地产营销等场景。核心采用SDXL通用室内设计模型和北欧极简LoRA,通过节点衔接实现自动化批量生成,能在短时间内将平面方案转化为逼真的三维效果图。该技术可提升设计呈现效率,辅助客户决策,并应用于教学研究领域。

Mr数据杨 3641

C++设计模式——适配器模式(Adapter Pattern)

C++设计模式——适配器模式(Adapter Pattern) 微信公众号:幼儿园的学霸 目录 文章目录C++设计模式——适配器模式(Adapter Pattern)目录定义定义作用/解决的问题适配器模式中的角色代码示例总结优缺点适用场景参考资料 定义 定义 Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t ot

leonardohaig的博客 1547

【cmd】Win10家庭版找不到 gpedit.msc (组策略)的解决方法

目录 一、创建cmd文件 二、以“管理员身份”运行“gpedit.cmd”文件 三、运行“gpedit.msc”命令查看组策略 一、创建cmd文件 (1)新建一个文件名为“gpedit.txt”的txt文本文档: (2)文本中写入以下内容: @echo off pushd "%~dp0" dir /b C:\Windows\servicing\Packages\Micros...

顾三殇 —— 博客空间(软件测试) 4万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

设计模式之适配器模式(Adapter Design Pattern)

适配器是接口转换器,为需要在一起工作但不兼容的两个接口桥梁。 适配器是常用的设计模式之一,现在是互联网时代,很多应用程序都会调用第三方的接口,比如支付接口、短信接口、验证码接口、数据对象存储接口等。而这些接口都是不一样的,如果在应用中要调用多个接口完成相同功能,就需要适配器。 适配器在生活中也很常见,如果手机充电器,笔记本充电器,都是电源适配器。在我国家里所使用的是220伏的电源电压,美国等国外有的使用110V电源电压,而普遍的电子产品一般所需的电源电压为5伏至20伏左右。如果没有电源适配器,这些电子产

xjj1314的专栏 461

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

设计模式教程:适配器模式(Adapter Pattern)

将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类能够一起工作。

遇见伯灵说的博客 1816

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

设计模式-05适配器模式Adapter Pattern

适配器模式摘要 适配器模式是一种结构型设计模式,用于解决接口不兼容问题。它通过将一个类的接口转换成客户期望的另一个接口,使原本不兼容的类能够协同工作。 核心特点: 包含目标接口(Target)、适配器(Adapter)和被适配者(Adaptee)三个角色 提供两种实现方式:类适配器(继承)和对象适配器(组合) 适用于复用现有类但其接口不符合需求的情况 典型应用: 如媒体播放器示例中,AudioPlayer通过适配器支持VLC和MP4等不同格式的播放器,而无需修改原有播放器代码。双向适配器还可实现接口间的双向

d3y1`5 81_09 900

设计模式-适配器模式(Adapter Pattern)

适配器模式 定义 将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。 分类 类适配器、对象适配器。 角色 目标接口:Target,该角色把其他类转换为我们期望的接口。 被适配者: Adaptee ,原有的接口,也是希望被适配的接口。 适配器: Adapter, 将被适配者和目标接口组合到一起的类。 适用场景 想要使用一个已经存在的类,但是它却不符合现有的接口规范,导致无法直...

kaven 4893

23种设计模式之适配器模式(Adapter Pattern)

、本篇文章将23种设计模式中的适配器模式,此篇文章为一天学习一个设计模式系列文章,后面会分享其他模式知识。

小威的博客 2万+

设计模式6:Adapter Pattern (适配器模式)

来自于:http://www.cnblogs.com/zhenyulu/articles/39386.html参考于:http://www.dofactory.com/Patterns/PatternAdapter.aspx一、 适配器(Adapter)模式适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。名称由来

薛敬明的专栏 2751

设计模式-适配器模式-adapter pattern

类适配器通过继承实现适配,适用于适配者接口较为固定的情况。对象适配器通过组合实现适配,提供了更高的灵活性,可以在运行时动态改变适配者对象。接口适配器通常用于适配多个具有不同接口的适配者,通过实现多个接口来统一调用。在实际开发中,选择哪种适配器模式取决于具体的设计需求和现有的代码结构。

wesigj的博客 1861

设计模式--适配器模式 Adapter Pattern

(1)适配器模式将某个类的接口转换成为客户端期望的另一个接口表示,主要的目的是兼容性,让原本应接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper).(2)适配器模式属于结构型模式(3)主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。

m0_63622279的博客 1009

【c++设计模式09】结构型1:适配器模式(Adapter Pattern)

适配器模式是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一个接口。适配器模式使得原本由于接口不兼容而无法合作的类能够协同工作。

junxuezheng的博客 2051

【设计模式】——适配器模式(Adapter Pattern)

适配器模式的核心思想是通过一个中间的适配器类,将两个不兼容的接口进行适配。这个适配器类将目标接口(客户端期望的接口)和被适配者类(已有的接口)连接起来,使得客户端可以通过目标接口调用被适配者类的功能。 适配器模式主要有三种形式:类适配器模式、对象适配器模式和接口适配器模式(默认适配器模式)。

J^T的博客 1118

设计模式之适配器模式(Adapter Pattern)

What: 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。 Why: 优点: 1.客户端通过适配器可以透明地调用目标接口; 2.复用了现存的类,不需要修改原有代码而重用现有的适配者类,符合开闭原则; 3.将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题; 缺点: 1.Java不支持多重继承,一次最多可以继承一个适配器类; 2....

qq_37212210的博客 444
上一篇: Qt开发:智能指针的介绍和使用
下一篇: 设计模式:桥接模式(Bridge Pattern)
TechNomad
博客等级 码龄2年 787粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值