当前位置: 首页 > news >正文

设计模式17-适配模式

设计模式17-适配模式

  • 动机
  • 定义与结构
  • C++代码推导
  • 总结
  • 应用
  • 具体应用示例

动机

  • 在软件系统中由于应用环境的变化常常需要将一些现存的对象。放到新的环境中去应用。但是新环境要求的接口是这些现存对象所不满足的。
  • 那么这种情况下如何应对这种迁移的变化?如何既能利用现有对象的良好实现用了满足新的应用环境所要求的接口。

适配器模式是解决两个接口不兼容的问题。通过适配器模式,我们可以将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。适配器模式主要用于以下场景:

  • 当你想使用一个已经存在的类,但它的接口不符合你的需求时。
  • 当你想创建一个可以重用的类,该类可以和不兼容的接口协同工作时。
  • 当你想使用一些现有的子类,但是不能进行子类化来匹配接口时,因为这会导致每个子类需要调整。

定义与结构

定义

  • 适配器模式将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

在这里插入图片描述

适配器模式包含以下主要角色:

  1. 目标(Target)接口:定义客户所需的接口。
  2. 适配者(Adaptee)类:定义一个已经存在的接口,这个接口需要适配。
  3. 适配器(Adapter)类:将适配者接口转换成目标接口,使得客户端可以通过目标接口与适配者进行通信。

适配器模式有两种实现方式:

  • 类适配器(Class Adapter):使用多重继承实现适配。
  • 对象适配器(Object Adapter):使用组合实现适配。

类适配器模式UML图:

----------------      ----------------      -----------------
|      Target     |<---|   Adapter    |<|  Adaptee         |
|----------------|   |----------------|   |---------------|
|+request()      |   |+request()      |   |+specificRequest|
-----------------      -----------------      ---------------

对象适配器模式UML图:

----------------      ----------------      ----------------
|      Target     |<---|   Adapter    |<| Adaptee          |
|----------------|   |----------------|   |----------------|
|+request()      |   |+request()      |   |+specificRequest|
-----------------   | -adaptee: Adaptee|   ------------------------------------

C++代码推导

类适配器模式:

#include <iostream>// 目标接口
class Target {
public:virtual void request() = 0;virtual ~Target() = default;
};// 适配者类
class Adaptee {
public:void specificRequest() {std::cout << "Adaptee specific request." << std::endl;}
};// 类适配器
class Adapter : public Target, private Adaptee {
public:void request() override {specificRequest();}
};// 客户端代码
int main() {Target* target = new Adapter();target->request(); // 调用适配器的方法delete target;return 0;
}

对象适配器模式:

#include <iostream>// 目标接口
class Target {
public:virtual void request() = 0;virtual ~Target() = default;
};// 适配者类
class Adaptee {
public:void specificRequest() {std::cout << "Adaptee specific request." << std::endl;}
};// 对象适配器
class Adapter : public Target {
private:Adaptee* adaptee;public:Adapter(Adaptee* adaptee) : adaptee(adaptee) {}void request() override {adaptee->specificRequest();}
};// 客户端代码
int main() {Adaptee* adaptee = new Adaptee();Target* target = new Adapter(adaptee);target->request(); // 调用适配器的方法delete target;delete adaptee;return 0;
}

总结

  • 适配器模式主要应用于希望服用一些现存的类可用于复用环境要求不一致的情况。在遗留代码复用嗯类库迁移等方面非常常用。

  • 世界模式书中定义了两种适配器模式的实现结构:对象适配器和类适配器。但是类适配器采用多继承的实现方式。一般不推荐使用。对象适配器采用对象组合的方式更符合松耦合的设计理念。

  • 适配器模式可以实现的非常灵活不必拘泥于设计模式书中定义的两种结构。例如完全可以将适配器模式中的现存对象作为新的接口方法参数,来达到适配的目的。

优点:

  1. 单一职责原则:可以将接口或数据转换代码从原始类中分离出来。
  2. 开闭原则:无需修改客户端代码即可引入新的适配器类。
  3. 灵活性高:类适配器使用多重继承,可以适配多个适配者类。对象适配器使用组合,可以在运行时对适配者进行替换。

缺点:

  1. 类适配器的缺点
    • 不支持适配多个适配者类,因为C++不支持多继承多个实现类。
    • 破坏了Adaptee类和Adapter类的独立性,因为适配器继承自适配者。
  2. 对象适配器的缺点
    • 在某些情况下,可能需要多次调用适配者的方法,导致性能开销较大。

应用

适配器模式在实际应用中非常广泛,常见的应用场景包括:

  1. 使用遗留代码库:当你想使用一个现有的类,但它的接口不符合你的需求时,可以使用适配器模式进行适配。
  2. 与第三方库集成:当你想使用第三方库,但它的接口与你的代码不兼容时,可以使用适配器模式进行适配。
  3. 处理多种接口:当你需要创建一个可以与多个不兼容接口进行交互的类时,可以使用适配器模式进行适配。

具体应用示例

以下是一个适配器模式的具体应用示例:将一个旧的日志系统适配到新的日志系统中。

旧日志系统:

#include <iostream>class OldLogger {
public:void oldLog(const std::string& message) {std::cout << "OldLogger: " << message << std::endl;}
};

新日志系统接口:

class NewLogger {
public:virtual void log(const std::string& message) = 0;virtual ~NewLogger() = default;
};

适配器类:

class LoggerAdapter : public NewLogger {
private:OldLogger* oldLogger;public:LoggerAdapter(OldLogger* logger) : oldLogger(logger) {}void log(const std::string& message) override {oldLogger->oldLog(message);}
};

客户端代码:

int main() {OldLogger* oldLogger = new OldLogger();NewLogger* logger = new LoggerAdapter(oldLogger);logger->log("This is a log message."); // 使用适配器进行日志记录delete logger;delete oldLogger;return 0;
}

通过上述示例,我们将旧的日志系统适配到新的日志系统接口中,使得客户端代码可以无缝使用旧的日志系统,同时保持代码的灵活性和可维护性。这就是适配器模式在实际开发中的典型应用。

相关文章:

设计模式17-适配模式

设计模式17-适配模式 动机定义与结构C代码推导总结应用具体应用示例 动机 在软件系统中由于应用环境的变化常常需要将一些现存的对象。放到新的环境中去应用。但是新环境要求的接口是这些现存对象所不满足的。那么这种情况下如何应对这种迁移的变化&#xff1f;如何既能利用现…...

react ant Input defaultValue={value}设置了value值以后,但是defalult没有赋值上,输入框也没有显示

在 React 中&#xff0c;defaultValue 是一个非受控属性&#xff0c;而 value 是一个受控属性。这两个属性都可以用于设置 Input 组件的值&#xff0c;但是它们的工作方式有所不同。 value&#xff1a;这是一个受控属性&#xff0c;意味着输入框的值由 React 状态控制。每当状态…...

大模型开发如何把一段文字变成一组token?

在大模型开发中&#xff0c;将一段文字变成一组token通常称为"tokenization"&#xff08;分词&#xff09;。这是自然语言处理中的一个关键步骤&#xff0c;主要是将连续的文本划分成离散的单元&#xff08;token&#xff09;&#xff0c;这些单元可以是单词、子词或…...

【MSYS】Windows Terminal 集成

Windows Terminal 集成 MSYS2安装在默认位置C:\msys64打开Windows Terminal打开JSON配置文件文件。 添加如下配置&#xff1a; "profiles": {"defaults": {},"list": [{"guid": "{71160544-14d8-4194-af25-d05feeac7233}"…...

Python酷库之旅-第三方库Pandas(056)

目录 一、用法精讲 211、pandas.Series.truncate方法 211-1、语法 211-2、参数 211-3、功能 211-4、返回值 211-5、说明 211-6、用法 211-6-1、数据准备 211-6-2、代码示例 211-6-3、结果输出 212、pandas.Series.where方法 212-1、语法 212-2、参数 212-3、功能…...

ZBrush入门使用介绍——4、笔刷选项说明

大家好&#xff0c;我是阿赵。   这次来看看ZBrush的笔刷的选项用法。 一、选择笔刷 点击笔刷&#xff0c;可以打开笔刷选择面板。 在最上面的Quick Pick&#xff0c;有最近使用过的笔刷&#xff0c;可以快速的选择。下面有很多可以选择的笔刷。但由于笔刷太多&#xff0c;…...

Java每日一练,技术成长不间断

目录 题目1.下列关于继承的哪项叙述是正确的&#xff1f;2.Java的跨平台特性是指它的源代码可以在多个平台运行。&#xff08;&#xff09;3.以下 _____ 不是 Object 类的方法4.以下代码&#xff1a;5.下面哪个流类不属于面向字符的流&#xff08;&#xff09;总结 题目 选自牛…...

传知代码-上下位关系自动检测方法(论文复现)

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 概述 本文复现论文 Hearst patterns revisited: Automatic hypernym detection from large text corpora[1] 提出的文本中上位词检测方法。 在自然语言处理中&#xff0c;上下位关系&#xff08;Is-a Relations…...

从零开始的MicroPython(二) GPIO及代码应用

上一篇&#xff1a;http://t.csdnimg.cn/mg2Qt 文章目录 ESP32(NodeMCU-32S)简介引脚注意事项 类与对象的概念MicroPython的GPIO使用文档解释machine.PinPin.irq 点灯 ESP32(NodeMCU-32S) 简介 NodeMCU-32S 是安信可基于 ESP32-32S 模组所设计的核心开发板。该开发板延续了 N…...

嵌入式day15

数组指针 能够指向整个数组 一维数组&#xff1a; &a&#xff0c;考察a的数据类型 int&#xff08;*p&#xff09;[10]&#xff1a;表示一个指向长度为10的一维整型数组的指针 二维数组&#xff1a; 指向函数的指针 函数的函数名&#xff0c;即为函数的入口地址&#x…...

【电池管理系统(BMS)-01】 | 电池管理系统简介,动力电池和储能电池区别

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…...

C++ STL partial_sum 用法

一&#xff1a;功能 计算部分和&#xff0c;即遍历序列中每个元素&#xff0c;计算前 i 个元素的累加和&#xff0c;并将结果存在 i 的位置上。 二&#xff1a;用法 #include <iostream> #include <vector> #include <numeric>int main() {std::vector<…...

诚宜开张圣听不应妄自菲薄

拾人牙慧孜孜不倦 青山依旧在几度夕阳红朝闻道夕死可矣 青山依旧在几度夕阳红 安能以血补天我计不成乃天命也臣本布衣躬耕南阳大丈夫宁死不辱尔要试我宝剑是否锋利吗又待怎样休教天下人负我竖子不足与谋皇天不佑天下英雄唯使君与操尔青光殷殷其灿如炎备不量力欲申大义于天下我…...

Vue3 加载条(LoadingBar)

效果如下图&#xff1a;在线预览 APIs LoadingBar 参数说明类型默认值必传containerClass加载条容器的类名stringundefinedfalsecontainerStyle加载条容器的样式CSSProperties{}falseloadingBarSize加载条大小&#xff0c;单位 pxnumber2falsecolorLoading加载中颜色string‘…...

《CSS创意项目实战指南》:点亮网页,从实战中掌握CSS的无限创意

CSS创意项目实战指南 在数字时代&#xff0c;网页不仅是信息的载体&#xff0c;更是艺术与技术的融合体。通过CSS&#xff0c;你可以将平凡的网页转变为引人入胜的视觉盛宴&#xff0c;让用户体验跃升至全新高度。《CSS创意项目实战指南》正是这样一本引领你探索CSS无限可能的…...

[FBCTF2019]RCEService (PCRE回溯绕过和%a0换行绕过)

json格式输入ls出现index.php 这道题原本是给了源码的&#xff0c;BUUCTF没给 源码&#xff1a; <?phpputenv(PATH/home/rceservice/jail);if (isset($_REQUEST[cmd])) {$json $_REQUEST[cmd];if (!is_string($json)) {echo Hacking attempt detected<br/><br/…...

vue3后台管理系统 vue3+vite+pinia+element-plus+axios上

前言 项目安装与启动 使用vite作为项目脚手架 # pnpm pnpm create vite my-vue-app --template vue安装相应依赖 # sass pnpm i sass # vue-router pnpm i vue-router # element-plus pnpm i element-plus # element-plus/icon pnpm i element-plus/icons-vue安装element-…...

Mysql的事务隔离级别实现原理

一、事务隔离级别 mysql支持四种事务隔离级别&#xff1a; 读未提交&#xff1a;一个事务可以读取到另一个事务还未提交的数据&#xff1b;读已提交&#xff1a;一个事务可以读取到另一个事务已经提交的数据&#xff1b;可重复读&#xff1a;同一个事务中&#xff0c;无论读取…...

计算机体系结构:缓存一致性ESI

集中式缓存处理器结构&#xff08;SMP&#xff09; 不同核访问存储器时间相同。 分布式缓存处理器结构&#xff08;NUMA&#xff09; 共享存储器按模块分散在各处理器附近&#xff0c;处理器访问本地存储器和远程存储器的延迟不同&#xff0c;共享数据可进入处理器私有高速缓存…...

log4j2漏洞练习(未完成)

log4j2 是Apache的一个java日志框架&#xff0c;我们借助它进行日志相关操作管理&#xff0c;然而在2021年末log4j2爆出了远程代码执行漏洞&#xff0c;属于严重等级的漏洞。apache log4j通过定义每一条日志信息的级别能够更加细致地控制日志生成地过程&#xff0c;受影响的版本…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...