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

一、什么是适配器模式(Adapter Pattern)

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一个接口。适配器模式主要用于解决不兼容接口之间的问题,使得原本由于接口不匹配而无法一起工作的类能够协同工作。

适配器模式涉及以下几个核心角色:

  1. 目标接口(Target Interface):客户端所期望的接口,适配器将现有的接口转换成这个目标接口。
  2. 适配器(Adapter):适配器类实现了目标接口,同时持有一个需要被适配的对象。适配器通过适配被适配对象的接口,使其能够符合目标接口的要求。
  3. 被适配对象(Adaptee):需要被适配的现有类。它可能具有与目标接口不同的接口。

适配器模式的目标是使不兼容的接口能够一起工作,同时也可以在一些情况下用来重用现有的类,而无需修改其源代码。

适配器模式可以分为两种类型:

  1. 类适配器模式:使用继承的方式将适配器与被适配对象结合起来,使适配器可以调用被适配对象的方法并实现目标接口。
  2. 对象适配器模式:使用组合的方式将适配器与被适配对象结合起来,使适配器通过调用被适配对象的方法来实现目标接口。

适配器模式在现实世界中的例子是,将电子设备从一个插头类型适配到另一个插头类型,以使其能够连接到不同的电源插座。

适配器模式提供了一种方式来处理不同接口之间的集成问题,使得系统中不同部分可以协同工作,从而提高了代码的灵活性和可维护性。

二、类适配器模式的代码样例

以下是一个使用C++实现类适配器模式的简单示例:

#include <iostream>

// 目标接口
class TargetInterface {
public:
    virtual void request() = 0;
};

// 被适配的类
class Adaptee {
public:
    void specificRequest() {
        std::cout << "Adaptee's specificRequest called." << std::endl;
    }
};

// 适配器类(类适配器)
class Adapter : public TargetInterface, public Adaptee {
public:
    void request() override {
        specificRequest();
    }
};

int main() {
    TargetInterface* target = new Adapter();
    target->request();

    delete target;
    return 0;
}

在这个示例中,我们有一个目标接口 TargetInterface,它定义了客户端期望的接口。然后有一个被适配的类 Adaptee,它具有与目标接口不同的接口。最后,我们创建了一个适配器类 Adapter,它继承了目标接口 TargetInterface 并继承了被适配类 Adaptee。适配器类的 request 方法通过调用被适配类的 specificRequest 方法来实现目标接口。

在主函数中,我们通过创建适配器对象,并将其视为目标接口的实例,从而可以调用 request 方法来实现被适配类的功能。

这个示例展示了类适配器模式的基本概念,通过继承来适配被适配的类的接口,使其能够符合目标接口的要求。

三、对象适配器模式的代码样例

以下是一个使用C++实现对象适配器模式的简单示例:

#include <iostream>

// 目标接口
class TargetInterface {
public:
    virtual void request() = 0;
};

// 被适配的类
class Adaptee {
public:
    void specificRequest() {
        std::cout << "Adaptee's specificRequest called." << std::endl;
    }
};

// 适配器类(对象适配器)
class Adapter : public TargetInterface {
public:
    Adapter(Adaptee* adaptee) : adaptee(adaptee) {}

    void request() override {
        adaptee->specificRequest();
    }

private:
    Adaptee* adaptee;
};

int main() {
    Adaptee* adaptee = new Adaptee();
    TargetInterface* target = new Adapter(adaptee);
    target->request();

    delete target;
    delete adaptee;
    return 0;
}

在这个示例中,我们依然有一个目标接口 TargetInterface,一个被适配的类 Adaptee,以及一个适配器类 Adapter。与之前不同的是,适配器类不再继承被适配的类,而是在构造函数中持有被适配类的实例。

适配器类的 request 方法通过调用被适配类的 specificRequest 方法来实现目标接口。

在主函数中,我们先创建了一个被适配类的实例 adaptee,然后将其传递给适配器类 Adapter 的构造函数来创建适配器对象。然后,我们通过适配器对象调用 request 方法来实现被适配类的功能。

这个示例展示了对象适配器模式的基本概念,通过组合和持有被适配的对象来适配其接口,从而使其能够符合目标接口的要求。

四、类适配器模式和对象适配器模式的区别

类适配器模式和对象适配器模式是适配器模式的两种不同实现方式,它们的区别主要体现在适配器与被适配对象之间的关系以及实现方式上。

类适配器模式:

  1. 关系:在类适配器模式中,适配器类通过继承被适配的类来实现适配。适配器同时拥有目标接口和被适配类的功能,因此可以通过调用被适配类的方法来实现目标接口。
  2. 实现方式:适配器类继承被适配类,可以直接访问被适配类的方法和属性,但也可能需要重新实现一些方法来适配目标接口。
  3. 结构复杂性:类适配器模式的结构相对较简单,但可能会受到被适配类的限制,因为继承只能应用于具有合适继承关系的类。

对象适配器模式:

  1. 关系:在对象适配器模式中,适配器类通过组合持有一个被适配的对象实例。适配器持有被适配对象的引用,通过调用被适配对象的方法来实现目标接口。
  2. 实现方式:适配器类在自己的方法中调用被适配对象的方法,实现了目标接口。适配器还可以在自己的方法中添加一些额外的逻辑。
  3. 灵活性:对象适配器模式更灵活,可以适配多个不同的被适配对象,而不受继承关系的限制。

选择哪种适配器模式:

  • 选择类适配器模式还是对象适配器模式取决于设计需求和被适配对象的特性。如果被适配对象是一个类,且希望通过继承来复用其功能,可以选择类适配器模式。如果被适配对象是一个接口或一个无法继承的类,或者希望适配多个不同的被适配对象,可以选择对象适配器模式。

总之,两种适配器模式都有各自的优势和用途,根据具体情况选择合适的实现方式。

五、使用适配器模式需要注意的问题

在使用适配器模式时,需要注意以下几个问题:

  1. 接口一致性:适配器模式的目的是将不兼容的接口转换成兼容的接口,但在适配过程中需要确保目标接口满足客户端的需求,否则可能会导致功能不正常或错误。
  2. 覆盖问题:在类适配器模式中,适配器类继承了被适配类的方法和属性。如果被适配类的方法与目标接口的方法同名,适配器可能需要覆盖被适配类的方法,以实现目标接口的需求。这可能导致子类方法的覆盖问题。
  3. 被适配对象的状态:在适配过程中,被适配对象的状态可能会受到影响。在适配器中调用被适配对象的方法时,需要确保对象的状态不会出现意外的变化。
  4. 灵活性和复用性:适配器模式可以在不同的场景中复用现有的类,但在适配过程中可能会引入一些特定的逻辑,这可能会影响到代码的灵活性和复用性。
  5. 过多的适配器:过度使用适配器模式可能会导致系统中存在大量的适配器类,从而增加代码的复杂性。需要根据实际情况权衡是否使用适配器模式。
  6. 性能问题:适配器模式可能会引入额外的开销,特别是在适配器的方法中涉及转换和逻辑时。需要在性能要求高的情况下进行评估和优化。

总之,适配器模式是一种用于解决接口不匹配问题的有用工具,但在使用时需要仔细考虑接口一致性、状态维护、代码复用等问题,以确保适配器能够正确地将不兼容的接口转换成兼容的接口。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/100961.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Netty-ChannelPipeline

EventLoop可以说是 Netty 的调度中心&#xff0c;负责监听多种事件类型&#xff1a;I/O 事件、信号事件、定时事件等&#xff0c;然而实际的业务处理逻辑则是由 ChannelPipeline 中所定义的 ChannelHandler 完成的&#xff0c;ChannelPipeline 和 ChannelHandler应用开发的过程…

[dasctf]misc05

盲水印 png里藏jpg&#xff0c;bwm.py可以提取含flag的图片

git学习笔记 | 版本管理 - 分支管理

文章目录 git学习笔记Git是什么仓库常见的命令commit 备注规范在文件下设置git忽略文件 .gitignore 版本管理git log | git reflog 查看提交日志/历史版本版本穿梭 git resetgit reset HEAD <file> git checkout -- fileName 丢弃工作区的修改git revertGit恢复之前版本的…

论文阅读_扩散模型_SDXL

英文名称: SDXL: Improving Latent Diffusion Models for High-Resolution Image Synthesis 中文名称: SDXL&#xff1a;改进潜在扩散模型的高分辨率图像合成 论文地址: http://arxiv.org/abs/2307.01952 代码: https://github.com/Stability-AI/generative-models 时间: 2023-…

3D视觉测量:形位公差 面对面平行度(附源码)

文章目录 0. 测试效果1. 基本内容1.1 面对面平行度概述2. 代码实现文章目录:3D视觉测量目录微信:dhlddxB站: Non-Stop_0. 测试效果 1. 基本内容 “平行度” 是用来描述两个或多个对象或方向之间的平行关系的度量。在几何和工程学中,平行度通常用于衡量物体、表面、线条或方向…

mac帧 arp

1.分片 2.MSS max segment size 3.跨网络的本质 就是经历很多的子网或者局域网 4.将数据从A主机跨网络送到B主机的能力 IP和mac IP解决的是路径选择的问题 5.数据链路层 用于两个设备&#xff08;同一种数据链路节点&#xff09;之间进行传递 6.以太网ether 7.局域网通…

圆圈加数字的css

方式一 .circle { width: 50px; height: 50px; border-radius: 50%; background-color: #f00; color: #fff; text-align: center; line-height: 50px; } .circle::before { content: attr(data-number); display: block; } <div class"circle" data-number"…

ChatGPT总结(持续更新)

目录 体验渠道 weTab CSDN-AI助手 其他插件 ChatGPT简介 ChatGPT主要用途 ChatGPT发展历程 GPT-4架构的特点和优势 ChatGPT的工作原理 神经网络和自然语言处理技术 Transformer模型 模型训练优化技巧 ChatGPT对程序员的帮助 与ChatGPT交互和提问技巧 ChatGPT未来…

50ETF期权开户平台(0门槛期权开户指南)

50ETF期权开户平台比较好的有&#xff1a;期权馆&#xff0c;期权科普馆&#xff0c;小熊期权&#xff0c;期权酱&#xff0c;财顺财经&#xff0c;财顺期权等&#xff0c;都是国内前十的期权分仓平台&#xff0c;下文为大家结算50ETF期权开户平台&#xff08;0门槛期权开户指南…

SoC 总线结构学习记录之系统存储总线(System Memory Bus)与私有设备总线

蜂鸟 E203 SOC总线结构&#xff1a;  蜂鸟 E203 内核 BIU 的系统存储接口 ICB 连接系统存储总线&#xff0c;通过其访问 SoC 中的若干存储组件&#xff0c;譬如 ROM&#xff0c;Flash 的只读区间等。  蜂鸟 E203 内核 BIU 的私有设备接口 ICB 连接私有设备总线&#xff0c…

mac电脑屏幕录制Berrycast Mac屏幕录制软件

Berrycast是一款为Mac设计的优秀屏幕录制软件&#xff0c;它让屏幕录制变得简单而高效。以下是Berrycast的一些主要特点&#xff1a; 简单的用户界面&#xff1a;Berrycast拥有直观和简洁的用户界面&#xff0c;使得用户可以轻松上手。高质量的视频输出&#xff1a;Berrycast能…

Sharding-JDBC介绍及分库分表实践

1.1 ShardingSphere简介 最早是当当网内部使用的一款分库分表框架&#xff0c;名字叫Sharding-JDBC&#xff0c;定位为轻量级 Java 框架&#xff0c;在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库&#xff0c;以 jar 包形式提供服务&#xff0c;无需额外部署和依…

机器人中的数值优化(六)—— 线搜索最速下降法

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…

C语言每日一练--Day(16)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字&#xff1a;寻找奇数 峰值 二分查找 &#x1f493;博主csdn个人主页&#xff1a;小…

《数字图像处理-OpenCV/Python》连载(4)图像的读取与保存

《数字图像处理-OpenCV/Python》连载&#xff08;4&#xff09;图像的读取与保存 本书京东优惠购书链接&#xff1a;https://item.jd.com/14098452.html 本书CSDN独家连载专栏&#xff1a;https://blog.csdn.net/youcans/category_12418787.html 第1章 图像的基本操作 为了方…

【MyBatisⅡ】动态 SQL

目录 &#x1f392;1 if 标签 &#x1fad6;2 trim 标签 &#x1f460;3 where 标签 &#x1f9ba;4 set 标签 &#x1f3a8;5 foreach 标签 动态 sql 是Mybatis的强⼤特性之⼀&#xff0c;能够完成不同条件下不同的 sql 拼接。 在 xml 里面写判断条件。 动态SQL 在数据库里…

vr智慧党建主题展厅赋予企业数字化内涵

现如今&#xff0c;VR全景技术的发展让我们动动手指就能在线上参观博物馆、纪念馆&#xff0c;不仅不用受时间和空间的限制&#xff0c;还能拥有身临其境般的体验&#xff0c;使得我们足不出户就能随时随地学习、传承红色文化。 很多党建展厅都是比较传统的&#xff0c;没有运用…

多级缓存 架构设计

说在前面 在40岁老架构师 尼恩的读者社区(50)中&#xff0c;很多小伙伴拿到一线互联网企业如阿里、网易、有赞、希音、百度、网易、滴滴的面试资格&#xff0c;多次遇到一个很重要的面试题&#xff1a; 20w的QPS的场景下&#xff0c;服务端架构应如何设计&#xff1f;10w的QPS…

国际版阿里云/腾讯云:弹性高性能计算E-HPC入门概述

入门概述 本文介绍E-HPC的运用流程&#xff0c;帮助您快速上手运用弹性高性能核算。 下文以创立集群&#xff0c;在集群中安装GROMACS软件并运转水分子算例进行高性能核算为例&#xff0c;介绍弹性高性能核算的运用流程&#xff0c;帮助您快速上手运用弹性高性能核算。运用流程…

企业架构LNMP学习笔记7

PHP介绍&#xff1a; HTML&#xff1a;超文本标记语言 http: 超文本传输协议 端口80 浏览器将html代码解析成web页面。 PHP&#xff1a;超文本预处理器。后端语言开发&#xff0c;页面上需要动态改变修改的&#xff0c;需要连接数据库查询数据&#xff0c;转为html。 主要…