C++设计模式_16_Adapter 适配器

Adapter 适配器也是属于“接口隔离”模式,也是间接思想在某一个层面的应用。

文章目录

  • 1. 动机( Motivation)
  • 2. 模式定义
  • 3. 结构 (Structure)
  • 4. Adapter 适配器的代码实现
  • 5. 要点总结
  • 6. 其他参考

1. 动机( Motivation)

  • 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。
  • 如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?

适配器模式是非常久远的模式,来源于我们的生活,以下是常见的适配器,适配器的意思对接不同接口的匹配需求
在这里插入图片描述
适配器的思想应用到类的设计中。

2. 模式定义

将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
----《设计模式》GoF

3. 结构 (Structure)

在这里插入图片描述Target 是未来的也就是希望的接口,Adaptee被适配者是以前的,遗留的接口,我们都希望他们保持不变,但是我们怎么将被适配的接口应用到新的环境,就需要具体的Adapter,Adapter类是继承自Target,我们在学很多模式的时候,常常强调,继承一个类,实际上表明我遵循基类定义的接口规范,在这里也就是Adapter具有Target一样的接口规范。同时可以看到有一个,同时可以看到一个组合,从 Adapter伸出一个箭头指到Adaptee。组合一个类就是支持一个实现的方式, Adapter就实现了把Adaptee往Target的转换。

上图是《设计模式》GoF中定义的Adapter 适配器的设计结构。结合上面的代码看图中最重要的是看其中稳定和变化部分,也就是下图中红框和蓝框框选的部分。
在这里插入图片描述
在具体实现过程中,Adapter 是千变万化的。

4. Adapter 适配器的代码实现

//目标接口(新接口)
class ITarget{
public:virtual void process()=0;
};//遗留接口(老接口)
class IAdaptee{
public:virtual void foo(int data)=0;virtual int bar()=0;
};//遗留类型
class OldClass: public IAdaptee{//....
};//对象适配器
class Adapter: public ITarget{ //继承
protected:IAdaptee* pAdaptee;//组合public://构造器Adapter(IAdaptee* pAdaptee){this->pAdaptee=pAdaptee;}virtual void process(){int data=pAdaptee->bar();pAdaptee->foo(data);}};//类适配器
class Adapter: public ITarget,protected OldClass{ //多继承}int main(){IAdaptee* pAdaptee=new OldClass();ITarget* pTarget=new Adapter(pAdaptee);pTarget->process();}

ITarget是目标接口,IAdaptee是遗留接口,由于某种内在的实现层面的关联性,适配器得能关联,可以把IAdapter转成一个ITarget

Adapter: public ITarget中Adapter继承自ITarget接口,就是遵循其定义的规范。实现virtual void process()=0;,在实现的过程中可能得转换过程如下:

    virtual void process(){int data=pAdaptee->bar();pAdaptee->foo(data);}

实际上真正的转换过程在某些平台上是非常复杂的,不像伪码表示的那么简单。第一要存在可转换,第二转换过程是相当复杂的。实际过程中可能类似process()的接口是比较多的,不像此处只有一个,通常可能是其他几个接口联合起来变成其中一个接口。
IAdaptee有一些老的类OldClass是继承自IAdaptee符合老的接口的。
真正在使用时代码如下:

int main(){IAdaptee* pAdaptee=new OldClass();    ITarget* pTarget=new Adapter(pAdaptee);pTarget->process();    
}

从此可以拿着一个旧的类 IAdaptee* pAdaptee=new OldClass();塞到Adapter里面ITarget* pTarget=new Adapter(pAdaptee);,当做一个新的类型,面向新接口的实现去使用。

在现实实现过程中,有一些细节可能不一样,比如stl中stack和queue的内部其实都使用了一个deque这样的一个内部的pAdaptee对象,它们都实现了它们的接口转成另外一个接口,那里可能没有明确的感觉谁是新的谁是旧的,只是说利用老的接口deque,转成stack和queue要求的接口,实际上是一个接口转换。那个里面是没有用指针,是直接将deque对象放进去,简单写成伪码就是如下:

class stack{deqeue container;};class queue{deqeue container;};

这种情况下,你可能没看到stack的接口是什么,因为stack本身既是接口又是实现,queue也是如此,但其总体符合Adapter设计模式的宗旨,可以将老的接口转成新的接口,所以我们很多时候也把它称为Adapter设计模式。

我们常常讲,大家在学习设计模式过程中,你不能太死板,不一定要追求GoF经典定义一模一样的代码。设计模式会有变体模式,不一定和经典的一致。但是最关键的是这个设计模式的场景,和它解决问题的手法,以及对变化点和稳定点的分离方式是不是符合模式的定义。

5. 要点总结

  • Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移等方面非常有用。
  • GoF23定义了两种Adapter模式的实现结构:对象适配器和类适配器。但类适配器采用“多继承”的实现方式,一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神。

上面所讲的是对象适配器,主要区别点是组合了一个对象

//对象适配器
class Adapter: public ITarget{ //继承
protected:IAdaptee* pAdaptee;//组合      
};

也有一些采用类适配器,主要区别点是多继承

//类适配器
class Adapter: public ITarget,protected OldClass{ //多继承               
}

使用继承OldClass带来的问题就是定死在OldClass,而没有灵活性(继承没有灵活性),而采用组合方式是十分具有灵活性的,IAdaptee* pAdaptee;可以指向OldClass,也可以指向AnotherClass

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

6. 其他参考

C++设计模式——适配器模式

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用HTTP2,新型DDoS攻击峰值破纪录

亚马逊、Cloudflare 和谷歌周二联合发布消息称,一种依赖于 HTTP/2 快速重置技术的攻击行为对它们造成了破纪录的分布式拒绝服务 (DDoS) 攻击。 根据披露的信息,该攻击自8月下旬以来便一直存在,所利用的漏洞被跟踪为CVE-2023-44487&#xff0c…

Hand Avatar: Free-Pose Hand Animation and Rendering from Monocular Video

Github: https://seanchenxy.github.io/HandAvatarWeb 1、结构摘要 MANO-HD模型:作为高分辨率网络拓扑来拟合个性化手部形状将手部几何结构分解为每个骨骼的刚性部分,再重新组合成对的几何编码,得到一个跨部分的一致占用场纹理建…

计算机视觉的相机选型

#你一般什么时候会用到GPT?# 目前市面上的工业相机大多是基于CCD(ChargeCoupled Device)或CMOS(Complementary Metal Oxide Semiconductor)芯片的相机。一般CCD制造工艺更加复杂,也会更贵一点! 1、CCD工…

网络协议--TCP的成块数据流

20.1 引言 在第15章我们看到TFTP使用了停止等待协议。数据发送方在发送下一个数据块之前需要等待接收对已发送数据的确认。本章我们将介绍TCP所使用的被称为滑动窗口协议的另一种形式的流量控制方法。该协议允许发送方在停止并等待确认前可以连续发送多个分组。由于发送方不必…

众和策略:数据要素市场腾飞在即 游戏市场持续高增长

昨日,两市股指早盘弱势下探,午后沪指在银行、电力等板块的带动下发力拉升,深成指、创业板指均走高。到收盘,沪指涨0.48%报2988.3点,深成指涨0.4%报9566.1点,创业板指涨0.65%报1875.86点;两市合计…

使用Jenkins触发gitlab的webhook

满足条件: 首先手动构建可以完成构建 例如: 打开项目点击配置 在“Build Triggers”栏勾选,Build when a change is pushed to GitLab. GitLab webhook ;如下 复制URL链接,我的链接是:http://192.168.44…

NAT技术与代理服务器

目录 一、NAT与NAPT技术 1.NAT技术 2.NAPT技术 (1)四元组的唯一性 (2)数据的传输过程 (3)NAPT的缺陷 二、代理服务器 1.正向代理和反向代理 2.代理服务器的应用 (1)游戏加…

小美的修路(最小生成树练习)

本题链接:登录—专业IT笔试面试备考平台_牛客网 题目: 样例: 输入 3 4 1 2 3 1 1 2 2 0 1 3 1 0 2 3 3 0 输出 2 1 3 思路: 由题意,这里建造的城市需要修路,且每个城市之间可以联通,且 是 1 …

2023年马丁·加德纳聚会数学魔术分享之《不只是奇偶性的魔术》回顾

早点关注我,精彩不错过! 我们的年度之约又来啦! 2023马丁聚会盛况 三年疫情的阴霾终于渐渐散去,今天本是有机会线下见一见网友们的一年。本来都收到武元元的通知,在考虑参加一次线下,哪知消息还没焐热就因故…

Ant Design Vue UI框架的基础使用,及通用后台管理模板的小demo【简单】

一、创建 VUE 项目 npm create vuelatest二、安装使用 ant-design-vue 安装脚手架工具 $ npm install -g vue/cli # OR $ yarn global add vue/cli使用组件 # 安装 $ npm i --save ant-design-vue4.x全局完整注册 import { createApp } from vue; import Antd from ant-de…

Python爬虫防止被封的方法:动态代理ip

目录 前言 一、为什么需要使用动态IP代理 1.网站反爬虫机制 2.突破本地IP限制 3.获取更多数据 二、Python爬虫动态IP代理的实现方法 1.使用第三方库 2.使用爬虫框架 三、预防被封的方法 1.代理池管理 2.请求间隔设置 3.使用多个代理 总结 前言 在进行网站爬取时&…

2023年香水行业数据分析:国人用香需求升级,高端香水高速增长

在人口结构变迁的背景下,“Z世代”作为当下我国的消费主力,正在将“悦己”消费推动成为新潮流。具备经济基础的“Z世代”倡导“高颜值”、“个性化”、“精致主义”,这和香水、香氛为代表的“嗅觉经济”的特性充分契合,因此&#…