结构型设计模式之适配器模式【设计模式系列】

news2024/11/25 10:50:00

系列文章目录

C++技能系列
Linux通信架构系列
C++高性能优化编程系列
深入理解软件架构设计系列
高级C++并发线程编程
设计模式系列

期待你的关注哦!!!
在这里插入图片描述

现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.

结构型设计模式之适配器模式

  • 系列文章目录
  • 一、适配器模式介绍
  • 二、桥接模式优缺点
    • 2.1 优点
    • 2.2 缺点
  • 三、桥接模式使用场景
  • 四、桥接模式实现

一、适配器模式介绍

⚠️ 意图:
适配器模式是用来做适配的,它将不兼容的接口转换可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。

⚠️ 主要解决:
主要解决软件系统中,常常要将一些“现存的对象”放到新的环境中,而新的环境要求接口是现对象不能满足的。

⚠️ 何时使用:
(1)系统需要现有的类,而此类的接口不符合系统的需要。
(2)想要建一个可以重复使用的类,用于一些与彼此之间没有太大关联的一些类,包括一些将来引进的类一起工作,这些源类不一定有一致的接口。
(3)通过接口转换,将一个类插入另一个类系中。

⚠️ 如何解决:
继承或依赖(推荐)。

适配器模式是用来做适配的,它将不兼容的接口转换可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。对于这个模式,我们常那USB转接头这样一个形象的例子来解释它。USB转接头充当适配器,通过转接,把两种不兼容的接口变得可以一起工作了。

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

  • 类适配器:类适配器通过使用继承关系来实现。
  • 对象适配器:符合组合复用原则,并且使用委托机制,对象适配器使用组合关系来实现。

在这里插入图片描述

图1_1 适配器模式类图

系统的数据和行为都正确,但接口不符时,我们应该考虑使用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。

想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式。

比如购买的第三方开发组件,该组件接口与我们自己系统的接口不相同,或者由于某种原因无法直接调用该组件,可以考虑适配器。

二、桥接模式优缺点

2.1 优点

  • 能提高类的透明性和复用,现有的类复用但不需要改变;

  • 解决了现有类和目标类不匹配的问题;

  • 目标类和适配器类解耦,提高程序扩展性;

  • 我们可以使用适配器模式开发自己的功能;

  • 符合开闭原则;

  • 具体的实现都在适配器中,客户端知道的只有适配器类,扩展的话,我们只需要扩展适配器就可以,而原有的类是不需要变化的。

2.2 缺点

  • 适配器编写过程中需要全面考虑,可能会增加系统的复杂性

  • 增加系统代码可读的难度

  • 如果过多的使用适配器,会让我们的系统非常凌乱,不易整理和进行把握。比如,我们调用第一个接口,其实内部已经被适配成了调用第二个接口的实现,这种情况在读代码的时候就很容易蒙圈,所以说增加了系统代码的可读的难度。

三、桥接模式使用场景

有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

  • 封装有缺陷的接口设计;

  • 统一多类的接口设计;

  • 替换依赖的外部系统;

  • 兼容老版本接口;

  • 适配不同格式的数据。

四、桥接模式实现

Adapter.h

#ifndef ADAPTER_ADAPTER_H
#define ADAPTER_ADAPTER_H

#include <iostream>

//目标接口类,客户需要的接口
class Target
{
public:
    Target();
    virtual ~Target();
    virtual void Request();//定义标准接口
};

//需要适配的类
class Adaptee
{
public:
    Adaptee();
    ~Adaptee();
    static void SpecificRequest();
};

//类模式,适配器类,通过public继承获得接口继承的效果,通过private继承获得实现继承的效果
class Adapter:public Target,private Adaptee
{
public:
    Adapter();
    ~Adapter() override;
    void Request() override;//实现Target定义的Request接口
};

//对象模式,适配器类,继承Target类,采用组合的方式实现Adaptee的复用
class Adapter1:public Target {
public:
    explicit Adapter1(Adaptee *adaptee);

    Adapter1();

    ~Adapter1() override;

    void Request() override;//实现Target定义的Request接口
private:
    Adaptee *_adaptee;

};
#endif //ADAPTER_ADAPTER_H

Adapter.cpp

#include "Adapter.h"

using namespace std;

Target::Target() = default;

Target::~Target() = default;

void Target::Request()
{
    cout << "Target::Request()" << endl;
}

Adaptee::Adaptee() = default;

Adaptee::~Adaptee() = default;

void Adaptee::SpecificRequest()
{
    cout << "Adaptee::SpecificRequest()" << endl;
}

//类模式的Adapter
Adapter::Adapter() = default;

Adapter::~Adapter() = default;

void Adapter::Request()
{
    cout << "Adapter::Request()" << endl;
    this->SpecificRequest();
    cout << "----------------------------" <<endl;
}

//对象模式的Adapter
Adapter1::Adapter1():_adaptee(new Adaptee)
{
}

Adapter1::Adapter1(Adaptee* _adaptee)
{
    this->_adaptee = _adaptee;
}

Adapter1::~Adapter1() = default;

void Adapter1::Request()
{
    cout << "Adapter1::Request()" << endl;
    this->_adaptee->SpecificRequest();
    cout << "----------------------------" <<endl;
}

main.cpp

#include <iostream>
#include "Adapter.h"

int main() {

    //类模式Adapter
    Target* pTarget = new Adapter();
    pTarget->Request();

    //对象模式Adapter1
    Adaptee* ade = new Adaptee();
    Target* pTarget1= new Adapter1(ade);
    pTarget1->Request();

    //对象模式Adapter2
    Target* Target2 = new Adapter1();
    Target2->Request();

    return 0;
}

在Adapter模式的两种模式中,有一个很重要的概念就是接口继承和实现继承的区别和联系。接口继承和实现继承是面向对象领域的两个重要的概念,接口继承指的是通过继承,子类获得了父类的接口,而实现继承指的是通过继承子类获得了父类的实现(并不统共接口)。在C++中的public继承既是接口继承又是实现继承,因为子类在继承了父类后既可以对外提供父类中的接口操作,又可以获得父类的接口实现。当然我们可以通过一定的方式和技术模拟单独的接口继承和实现继承,例如我们可以通过private继承获得实现继承的效果(private继承后,父类中的接口都变为private,当然只能是实现继承了。),通过纯抽象基类模拟接口继承的效果,但是在C++中pure virtual function也可以提供默认实现,因此这是不纯正的接口继承,但是在Java中我们可以interface来获得真正的接口继承了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Type [unknown] not present(主要问题是jar冲突)

解决方案&#xff1a;1选择pom.xml 2鼠标移动到打开的pom.xml点击右键选择maven 显示图 3ctrl鼠标左键移动找到红线 可以看到引入冲突 4按照实际需求对pom.xml的引入进行增删或者版本升级降级&#xff0c;直到以下图标中没有红线冲突即可

SQL注入 三范式

学习目标 了解三范式的要求 1. 什么是范式 设计关系数据库时&#xff0c;遵从不同的规范要求&#xff0c;设计出合理的关系型数据库&#xff0c;这些不同的规范要求被称为不同的范式&#xff0c;各种范式呈递次规范&#xff0c;越高的范式数据库冗余越小。 实际上家用电器都有…

香农极限是如何影响光纤容量的

1 引言 上世纪末&#xff0c;DWDM技术开始在干线通信中使用并迅速普及。虽然当时DWDM系统的容量只有402.5G&#xff0c;但实验室中DWDM支持的波道数甚至超过了1000波&#xff0c;单波道速率也飙到了惊人的160G&#xff08;超1000波和单波160G是两个独立事件&#xff09;。人们普…

docker快速搭建并使用Zabbix

docker搭建并使用Zabbix 0 zabbix基础知识 zabbix-server zabbix 的server 端&#xff0c;负责接收agent发送过来的监控数据&#xff0c;并且提供zabbix的所有核心功能。database 用于存储监控数据和配置信息的数据库&#xff0c;目前常用的有mysql和postgresql两种数据库。za…

【AutoSAR应用软件设计】

AutoSAR总体架构 是本文讲解内容。 接口类型 AUTOSAR接口 –SWCs和/或BSW模块交换的信息–独立于实施/网络/硬件–端口接口 标准化AUTOSAR接口 –AUTOSAR接口–标准化的语法和语义–标准化端口接口 标准化接口 –标准化API–通常为特定编程语言&#xff08;“C”&#x…

火狐浏览器鼠标点击页面区域文字时,出现光标的问题

点击一些资源卡片和查看别的页面时&#xff0c;发现点击非输入框的地方&#xff0c;出现了光标&#xff0c;误以为光标处可以填写东西&#xff0c;就试着敲了几次键盘&#xff0c;发现没有任何反应&#xff1b;然后就叫开发那个页面的同事过去看看&#xff1b;那个同事按F12各种…

如何监控Linux和Oracle数据库运行状态

背景: 在生产环境中,一般可能会发生服务器宕机或者数据库宕机的情况,如何准确的把握找准”生产事故“的具体发生时间,其实有很多方法,可以借助第三方的监控软件或者其他收费软件。 但是本人就是穷逼一个,不可能买或者使用盗版的三方软件。所有设计了以下流程检测Linux和…

16_LinuxINPUT子系统

目录 input子系统简 input驱动编写流程 注册input_dev 上报输入事件 input_event结构体 按键input驱动程序编写 编写测试APP 运行测试 input子系统简 按键、鼠标、键盘、触摸屏等都属于输入(input)设备,Linux内核为此专门做了一个叫做input子系统的框架来处理输入事件。…

node中间件-express框架

文章目录 前置 Express安装1. 基本使用2. 中间件2.1 中间件应用 3. 中间件的注册方式3.1 普通中间件的注册3.2 path匹配中间件3.3 method与路径匹配3.4 案列中间件匹配与执行方法 4. 中间件request数据解析4.1 解析request body中间件4.2 urlencoded解析 5. 第三方中间件5.1 mo…

CHI协议保序之Comp保序

一致性系统中&#xff0c;需要 memroy model 使用 multi-copy atomicity; 一致性系统中&#xff0c;使用三种保序方式&#xff1b; Completion response □ Comp 响应 表示当前的请求&#xff0c;己经达到了 POC/POS, POC/POS 将保证其命令的执行顺序和接收的顺序是一致的&…

Python(三十三)分支结构——嵌套if的使用

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

Android Studio下载

目录 确定版本下载地址 确定版本 如果是入职工作&#xff0c;先和同事确定好版本。因为每个项目使用的gradle插件版本&#xff0c;是在根目录的build.gralde文件中统一定义的&#xff0c;这个文件在添加第三方库&#xff08;例如GreenDao&#xff0c;Arouter等&#xff09;或者…

SpringBoot项目的创建

等待maven下载完成 删除无用文件 此时我们就创建成功了

Shiro权限绕过漏洞(CVE-2020-1957,CVE-2020-11989、CVE-2020-13933)

一、Apache Shiro Apache Shiro 是一个强大且易用的Java安全框架,能够用于身份验证、授权、加密和会话管理。 二、Shiro漏洞指纹&#xff08;部分&#xff09; 1、在请求包的cookie中有remember字段赋任意值 2、返回包中存在set-Cookie&#xff1a;remeberMedeleteMe 三、受…

通过宝塔面板将vue项目放到阿里云服务器(两个vue项目)

前提条件&#xff1a; 端口提前开放所需环境安装好&#xff08;Nginx node…&#xff09;以及打包好的vue文件&#xff08;dist&#xff09; 第一步&#xff1a;上传文件到自定义目录 第二步&#xff1a;在首页找到Nginx软件并配置 第三步&#xff1a;配置具体的配置 这里说…

「雕爷学编程」Arduino动手做(39)——DS18B20温度传感器3

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…

厦门枫叶时代看电视的新趋势

随着“5G电视”技术的不断普及和城市数字化转型的加速&#xff0c;电视行业也在发生着翻天覆地的变化。在这个背景下&#xff0c;第28届上海电视节推出了高端论坛板块——“白玉兰对话”&#xff0c;共同探讨电视行业的未来发展。其中备受瞩目的中国电视剧发展论坛&#xff0c;…

荔枝派Zero(全志V3S)驱动开发之USB摄像头

文章目录 前言一、内核配置 UVC二、编译内核并烧录到 SD 卡三、上电测试四、mjpeg-streamer 视频流服务器测试1、jpeg 库的移植2、移植 mjpeg-streamer①、前置软件②、下载 mjpg-streamer 源码③、修改 mjpg-streamer 源码④、编译 mjpg-streamer 源码 3、搬移文件到 nfs 目录…

2023/07/23

1. 必须等待所有请求结束后才能执行后续操作的处理方式 方式一&#xff1a; async func () {const p1 await api1();const p2 await api2();const p3 await api3();Promise.all([p1, p2, p3]).then(res > {后续操作...}) }方式二&#xff1a;待补充 2. flex 弹性盒子布…

300M的联通宽带,电脑直接连接光猫只有100M;电脑连接路由器,然后路由器连接光猫却有300M???

1. 现象 300M的联通宽带&#xff0c;用了小半年之后发现网络比以前满&#xff0c;通过https://www.speedtest.cn网站测试发现只有100M 2. 猜测 难道是联通这帮人&#xff0c;偷偷把我网速降到了100M&#xff1f;&#xff1f;&#xff1f; 3. 排查过程 打电话让联通师傅上门排查…