C# 结构型设计模式----适配器模式

1、简介

简单的说就是将一个类的接口转换成客户希望的另一个接口

举例理解:

你买了一个苹果手机,但是家里的数据线都是安卓的,你想用安卓的线充你的苹果手机,那你就需要一个转接头。适配器模式就是适用于这种情况。

适配的本质就是转换,将不满足使用条件的东西通过第三方类进行加工处理成可使用的东西。适配器模式用来解决现有对象与客户端期待接口不一致的问题。

基本角色:

  • 目标角色(Target):描述了其他类与客户端代码合作时必须遵循的协议。(就是你要调用的接口,相当于苹果充电头)
  • 客户角色(Client):与符合Target接口的对象协同。(就是调用者,需求主体--也就是你)
  • 被适配(服务类,功能类)(Adaptee):定义一个已经存在并已经使用的接口,这个接口需要适配。 客户端与其接口不兼容, 因此无法直接调用其功能。(相当于安卓充电线)
  • 适配器(Adapter) :适配器模式的核心。适配器接受客户端通过适配器接口发起的调用,同时根据其内在逻辑调用对应服务类。客户端代码只需通过接口与适配器交互即可, 无需与具体的服务类耦合。(相当于转接头)

2、适用场景

系统需要复用现有类,但是接口又与复用环境要求不一致的情况。

旧系统与新系统的兼容:

可以使新系统能够无缝地与老旧系统进行通信。

第三方组件的集成:

适配器可以将第三方组件的接口转换为符合我们系统需求的接口形式,从而能够顺利地集成到我们的系统中。

多个类库之间的互操作:

适配器模式可以起到桥梁的作用。

举例:例如海康SDK之类的dll文件没有.NET Core版本的,只有Java的支持跨平台,这时候我们需要使用就可以直接引入Java版本的SDK,用适配器生成接口即可。

3、创建方式

适配器模式分为两类:类适配器对象适配器

下面以苹果手机使用安卓充电线为例

3.1 类适配器:

被适配者

 /// <summary>/// 被适配者,,安卓线/// </summary>public class MyAdaptee{/// <summary>/// 你希望使用的方法/// </summary>public void CD(){Console.WriteLine("我开始充电");}}

适配器

/// <summary>
/// 适配器---转接头
/// </summary>
public  class MyAdapter : MyAdaptee, MyTarget
{public void ZH(){base.CD();//使用充电功能,但是方法由CD变为了ZH}
}

目标角色

 /// <summary>/// 目标角色---苹果充电线,这里可以写成抽象类或者接口/// </summary>public interface MyTarget{void ZH();}

客户端角色(使用者)

 /// <summary>/// 使用,客户端角色/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void WTBtn_Click(object sender, EventArgs e){//假如你能直接使用安卓线,也就是被适配者Console.WriteLine("安卓手机需要充电\n");MyAdaptee adaptee = new MyAdaptee();adaptee.CD();//你买了苹果手机,没法直接用安卓手机冲了,加个转接头MyTarget my = new MyAdapter();Console.WriteLine("苹果手机需要充电\n");my.ZH();}

优点:
1、可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”
2、可以重新定义Adaptee(被适配的类)的部分行为,因为在类适配器模式中,Adapter是Adaptee的子类
3、仅仅引入一个对象,并不需要额外的字段来引用Adaptee(被适配者)实例(这个即是优点也是缺点)。
缺点:
1、用一个具体的Adapter(适配器)类对Adaptee(被适配者)和Target(目标角色)进行匹配,当如果想要匹配一个类以及所有它的子类时,类的适配器模式就不能胜任了。因为类的适配器模式中没有引入Adaptee的实例。
2、采用了 “多继承”的实现方式,带来了不良的高耦合。 

3.2 对象适配器:

被适配者(与类适配器一致)

 /// <summary>/// 被适配者,,安卓线/// </summary>public class MyAdaptee{/// <summary>/// 你希望使用的方法/// </summary>public void CD(){Console.WriteLine("我开始充电");}}

 适配器(区别在这)

 /// <summary>/// 适配器---转接头/// </summary>public  class MyAdapter : MyTarget{MyAdaptee adaptee = new MyAdaptee();public void ZH(){adaptee.CD();//使用充电功能,但是方法由CD变为了ZH}}

目标角色(与类适配器一致)

 /// <summary>/// 目标角色---苹果充电线,这里可以写成抽象类或者接口/// </summary>public interface MyTarget{void ZH();}

客户端角色

 /// <summary>/// 使用,客户端角色/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void WTBtn_Click(object sender, EventArgs e){//假如你能直接使用安卓线,也就是被适配者Console.WriteLine("安卓手机需要充电\n");MyAdaptee adaptee = new MyAdaptee();adaptee.CD();//你买了苹果手机,没法直接用安卓手机冲了,加个转接头MyTarget my = new MyAdapter();Console.WriteLine("苹果手机需要充电\n");my.ZH();}

 优点:
1、可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”(这点是两种实现方式都具有的)
2、采用 “对象组合”的方式,更符合松耦合。
缺点:
1、使得重定义Adaptee的行为较困难,这就需要生成Adaptee的子类并且使得Adapter引用这个子类而不是引用Adaptee本身。 

总结:

由例子可以看出类适配与对象适配在于一个继承被适配者,一个实例化被适配者。 类适配器采用“多继承”的实现方式,在C#语言中,如果被适配角色是类,Target的实现只能是接口,因为C#语言只支持接口的多继承的特性。在C#语言中类适配器也很难支持适配多个对象的情况,同时也会带来了不良的高耦合和违反类的职责单一的原则,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神,对适配的对象也没限制,可以一个,也可以多个,但是,使得重定义Adaptee的行为较困难,这就需要生成Adaptee的子类并且使得Adapter引用这个子类而不是引用Adaptee本身。

END--------------------------------------------------------------------------------------------------------------------------

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

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

相关文章

感受野是什么?有什么用?从感受野的角度理解,FCN要堆叠卷积层

参考&#xff1a;感受野 1.感受野是什么 感受野(receptive field)这一概念来自于生物神经科学&#xff0c;是指感觉系统中的任一神经元&#xff0c;其所受到的感受器神经元的支配范围。感受器神经元就是指接收感觉信号的最初级神经元。 而在卷积神经网络中&#xff0c;感受野…

C++基础三(构造函数,形参默认值,函数重载,单例模式,析构函数,内联函数,拷贝构造函数)

C有六个默认函数&#xff0c;分别是&#xff1a; 1、默认构造函数; 2、默认拷贝构造函数; 3、默认析构函数; 4、赋值运算符; 5、取址运算符; 6、取址运算符const; 构造函数 构造函数(初始化类成员变量)&#xff1a; 1、属于类的成员函数之一 …

LEADTOOLS 版本 23 现已发布,引入了 Excel API等众多新功能!

LEADTOOLS 以其在全世界主要国家中占有的市场领导地位&#xff0c;在数码图象开发工具领域中已成为既定的全球领导者&#xff0c;其不断发展和扩展功能&#xff0c;以帮助开发人员构建更好、更强大的应用程序。最新发布的 LEADTOOLS 版本 23引入了许多新功能&#xff0c;包括新…

鸿蒙系统的优势 不足以及兼容性与未来发展前景分析

2024 年 10 月 22 日&#xff1a;华为正式发布原生鸿蒙操作系统 HarmonyOS next&#xff0c;并正式命名为 HarmonyOS 5&#xff0c;这是鸿蒙系统史上最大的升级&#xff0c;实现了国产操作系统从底层架构到应用生态的全面自主可控。 鸿蒙系统与安卓、iOS 相比&#xff0c;具有…

Hive 2.x 的安装与配置

Hive 2.x 的安装与配置 1 简介 基于Hadoop的一个数据仓库工具&#xff0c;可将结构化数据文件映射为一张数据库表&#xff0c;并提供简单[SQL]查询&#xff0c;可将SQL语句转换为MapReduce任务进行运行。 优点 学习成本低&#xff0c;可通过类SQL语句快速实现简单的MapReduce统…

关于图像客观指标的调试总结

1、问题背景 工作中经常有调试图像客观指标的需求&#xff0c;很容易遇到我们自己的环境测试是过的&#xff0c; 但客户那边的环境就是测不过&#xff0c;这时候该怎么办呢&#xff1f; 2、问题分析 首先要改变以往的工作思路&#xff0c;在调试的过程中不能说指标过了就完了&a…

VulkanTutorial(14·descriptor,uniform buffer)

Uniform buffers Descriptor layout and buffer 我们将继续学习3D图形&#xff0c;这需要一个模型-视图-投影矩阵&#xff0c;因此我们要更改向vertex shader传输的数据&#xff0c;也就是通过vertex buffer 但是当实时渲染&#xff0c;每一帧这些数据都有可能变化&#xff0…

Kafka存储机制大揭秘:从日志结构到清理策略的全面解析

文章目录 一、前言二、日志存储结构1.日志文件结构2.topic3.partition4.segment索引文件5.message结构6.message查找过程 三、存储策略1.顺序写2.页缓存3.零拷贝4.缓存机制 四、日志格式演变1.V0 版本2.V1 版本3.V0/V1消息集合4.V2 版本消息格式5.V2版本消息集合 五、偏移量维护…

基于OSS搭建在线教育视频课程分享网站

OSS对象存储服务是海量、安全、低成本、高持久的存储服务。适合于存储大规模非结构化数据&#xff0c;如图片、视频、备份文件和容器/虚拟机镜像等。 安装nginx wget https://nginx.org/download/nginx-1.20.2.tar.gz yum -y install zlib zlib-devel gcc-c pcre-devel open…

HCIA笔记整合

第一部分&#xff1a; OSI七层模型 应用层&#xff1a;人机交互 抽象语言--------编码 表示层&#xff1a;编码------二进制 会话层&#xff1a;提供会话号 传输层&#xff1a;TCP/UDP 分段&#xff08;收到MTU值的限制&#xff09; MTU&#xff1a;最大传输单元&#xff…

如何选择到印尼的海运代理

如何选择到印尼的海运代理 选择合适的海运代理的重要性 海运代理负责安排货物从发货地到目的地的整个运输过程&#xff0c;包括装运、清关、仓储等服务。一个可靠的海运代理能确保货物安全准时到达&#xff0c;并帮助企业节省时间和成本。 选择海运代理需考虑的主要因素 公司…

RK3588的QT交叉编译环境搭建

主要参考为RK3568或RK3288开发板创建交叉编译环境{采用amd64的ubuntu系统配置交叉编译arm64开发环境}(保姆级包括安装QT)超详细记录版_rk3568交叉编译-CSDN博客 先说一下&#xff0c;使用的Ubuntu20.04.5版本&#xff0c;qt源码用的5.14.2版本&#xff0c;交叉编译器使用RK3588…

【Linux】一些Shell脚本编程基础题

目录 一、比较两个数的大小 二、求1-100的素数和 三、编写shell脚本&#xff0c;输入一个数字n并计算1~n的和&#xff0c;同时要求如果输入的数字小于1&#xff0c;则重新输入&#xff0c;直到输入正确的数字为止。 四、编写一个shell脚本用来进行成绩等级评定&#xff0c;…

数据的表现形式(2)

汉字字形码 字形码也叫字模或汉字输出码。字形码是表示汉字字型信息的编码&#xff0c;用来实现计 算机对汉字的输出 如一个16*16点阵的字形码就需要16*16/8个字节的存储空间 二进制的运算 在定点二进制运算中&#xff0c;减法运算一般通过【补码运算的二进制加法器】 进制三要…

Vision - 开源视觉分割算法框架 Grounded SAM2 配置与推理 教程 (1)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/143388189 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Ground…

深度学习基础—语言模型和序列生成

引言 深度学习基础—循环神经网络&#xff08;RNN&#xff09;https://blog.csdn.net/sniper_fandc/article/details/143417972?fromshareblogdetail&sharetypeblogdetail&sharerId143417972&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 上…

leetcode-3-无重复字符的最长子串

题解&#xff1a; 1、初始化一个字典dic_hash{}。 2、初始化左指针i-1&#xff0c;右指针j为s的索引。 #3、初始化变量res1用3 2Q#来 |} 】、 代码&#xff1a;

readhat虚拟机基本操作

1.用cat显示/etc/passwd&#xff0c;并显示行号 2.在当前目录下创建空文件夹/web/test1 3.查看当前工作目录的命令 4.显示环境变量$PATH 5. 查看/tmp/目录的使用空间 6. 删除空目录old 要删除old,要先建立old目录---mkdir old&#xff0c;然后ls查看是否建立成功&#xff0c;再…

Java面试经典 150 题.P80. 删除有序数组中的重复项 II(004)

本题来自&#xff1a;力扣-面试经典 150 题 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台https://leetcode.cn/studyplan/top-interview-150/ 题解&#xff1a; class Solution {public int removeDuplicates(int[] nums)…

基尼指数(Gini Impurity)的理解和计算

基尼不纯度简介 - Gini Impurity - 吕汉鸿 - 博客园 先看上面这个博文&#xff01;&#xff01;&#xff01;然后再看下面的&#xff0c;下面这个原博文有一点问题。已修正&#xff0c;修正后的完整内容如下 一、基尼指数的概念 基尼指数&#xff08;Gini不纯度&#xff09;…