.NET 设计模式—适配器模式(Adapter Pattern)

简介

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

在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。

适配器有类适配器和对象适配器两种类型,二者的意图相同,只是实现的方法和适用的情况不同。类适配器采用继承来实现,对象适配器则采用组合的方法来实现。

角色

  • 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
  • 需要适配的类(Adaptee):需要适配的类或适配者类。
  • 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。  

优点

  • 通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。
  • 复用了现存的类,解决了现存类和复用环境要求不一致的问题。
  • 将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
  • 一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。

缺点

  • 对于对象适配器来说,更换适配器的实现过程比较复杂。(可以用工厂模式解决)

应用场景

  • 系统需要使用现有的类,而此类的接口不符合系统的需要。
  • 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。
  • 仅对对象适配器而言,在设计里,需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。

案例

我们开发了一个项目,项目中采用了一个第三方的日志组件来记录日志,但是现在第三方日志组件实现的,现在我们自己开发了一个日志组件,我们想把项目中的日志组件替换为我们自己开发的,但是我们自己的开发的日志组件并没有实现第三方组件的接口,这个时候要怎么处理?

对象适配器实现(推荐)

  • 目标接口
/// <summary>
/// 目标接口
/// </summary>
public interface ILog
{/// <summary>/// 写日志的方法/// </summary>public void Write(string logCommand);
}
  • 需要适配的类
/// <summary>
/// 新开发的的日志接口类
/// </summary>
public abstract class ILogAbapter
{/// <summary>/// 新的写日志的方法/// </summary>/// <param name="logCommand"></param>public abstract void NewWrite(string logCommand);
}/// <summary>
/// 需要适配的数据库日志类
/// </summary>
public class DbLog : ILogAbapter
{public override void NewWrite(string logCommand){Console.WriteLine($"记录到数据库中:{logCommand}");}
}/// <summary>
/// 需要适配的文件日志类
/// </summary>
public class FileLog : ILogAbapter
{public override void NewWrite(string logCommand){Console.WriteLine($"记录到日志文件中:{logCommand}");}
}
  • 适配器
/// <summary>
/// 对象适配器
/// </summary>
public class LogAdapter : ILog
{private readonly ILogAbapter _logAdapter = null;public LogAdapter(ILogAbapter logAdapter){_logAdapter = logAdapter;}public void Write(string logCommand){_logAdapter.NewWrite(logCommand);}
}
  • 上层应用调用
{#region 对象适配器LogAdapter fileLog = new LogAdapter(new FileLogAdapter());fileLog.Write("hello word");LogAdapter dbLog = new LogAdapter(new DbLogAdapter());dbLog.Write("hello word");#endregion
}

类适配器实现

  • 目标接口
/// <summary>
/// 目标接口
/// </summary>
public interface ILog
{/// <summary>/// 写日志的方法/// </summary>public void Write(string logCommand);
}
  • 需要适配的类
/// <summary>
/// 新开发的的日志接口类
/// </summary>
public abstract class ILogAbapter
{/// <summary>/// 新的写日志的方法/// </summary>/// <param name="logCommand"></param>public abstract void NewWrite(string logCommand);
}/// <summary>
/// 需要适配的数据库日志类
/// </summary>
public class DbLog : ILogAbapter
{public override void NewWrite(string logCommand){Console.WriteLine($"记录到数据库中:{logCommand}");}
}/// <summary>
/// 需要适配的文件日志类
/// </summary>
public class FileLog : ILogAbapter
{public override void NewWrite(string logCommand){Console.WriteLine($"记录到日志文件中:{logCommand}");}
}
  • 适配器
/// <summary>
/// 数据库日志适配器
/// </summary>
public class DbLogAdapter : DbLog, ILog
{public void Write(string logCommand){NewWrite(logCommand);}
}/// <summary>/// 文件日志适配器/// </summary>public class FileLogAdapter : FileLog, ILog{public void Write(string logCommand){NewWrite(logCommand);}}
  • 上层应用调用
{#region 类适配器ILog fileLog = new FileLogAdapter();fileLog.Write("hello word");ILog dbLog = new DbLogAdapter();dbLog.Write("hello word");#endregion
}

总结

  • 对象适配用处是,可以使Adaptee不必实现不需要的方法,具体就是其表现形式就是父类实现缺省方法,而子类只需实现自己独特的方法。
  • 适配器类可以是抽象类。
  • 带参数的适配器模式。使用这种办法,适配器类可以根据参数返还一个合适的实例给客户端。

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

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

相关文章

ThreadLocal加切面实现线程级别的方法缓存

1、实现效果 当一个请求线程多次请求A方法时,只会触发一次A方法的实际调用,会将方法结果缓存起来,避免多次调用。 2、实现过程 1. 需要一个注解ThreadLocalCache,在需要缓存的方法上加上该注解 2. 需要一个切面,借助ThreadLocal,将结果缓存起来,利用环绕通知来实现方法拦截从…

vue项目使用element ui

目录 1、创建一个vue项目 2、找到element官网&#xff0c;点击指南&#xff0c;找到安装栏 3、 找到使用包管理器&#xff0c;复制命令 4、在main.js中引入element 5、使用element ui 6、找到App.vue&#xff0c;导入Button.vue文件&#xff0c;保存启动项目 1、创建一个vu…

MySQL复制拓扑1

文章目录 主要内容一.安装MySQL服务器1.MySQL 安装程序和其它文件保存在下发的 mysql8-files.iso 镜像文件中&#xff0c;可以使用虚拟光驱来提取到 Linux 文件系统。代码如下&#xff08;示例&#xff09;: 2.将 MySQL8.0 程序解压到 /opt 目录&#xff0c;再创建到 MySQL 默认…

阿里巴巴Java开发 单元测试和安全规约

目录 前言 1.单元测试 2.安全规约 前言 单元测试和安全规约依次分为【重要】、【建议】、【参考】,整理单元测试和安全规约为了更好处理代码中bug,使得代码更加安全。 1.单元测试 1.【重要】好的单元测试必须遵守 AIR 原则。 说明:单元测试在线上运行时,感觉像空气(…

闪站侠洗护管理系统,洗衣洗鞋小程序软件定制,干洗连锁店软件系统搭建;

闪站侠洗护管理系统&#xff0c;洗衣洗鞋小程序软件定制&#xff0c;干洗连锁店软件系统搭建&#xff1b; 为了让每一个洗衣洗鞋工厂与门店的连接更加高效便捷&#xff0c;送洗流程更加简单轻松&#xff0c;拽牛科技倾心打造洗衣洗鞋管理软件。我们的目标是通过高效和优质的服务…

双指针(复习)

基本概念 双指针:在区间操作时&#xff0c;利用两个下标同时遍历&#xff0c;进行高效操作 双指针利用区间性质可以把0(n2)时间降低到0(n) 蓝桥532 import os import sys# 请在此输入您的代码 w int(input()) n int(input()) b [] ans 0 for i in range(n):b.append(int(…

复现chatgpt_ros,需要openapi key

&#xff11;&#xff0e; 前置工作&#xff1a; 现在&#xff55;buntu系统是20.04ros1&#xff0c;现在用docker新建并安装ros2&#xff1a; 最简单的&#xff0c;用大佬的一键安装&#xff1a; wget http://fishros.com/install -O fishros && . fishros 其次自己装…

基于沙漏 Tokenizer 的高效三维人体姿态估计框架HoT

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;基于沙漏 Tokenizer 的高效三维人体姿态估计框架HoT1、研究背景2、提出方法3、模块详细3.1、什么是HoT3.2、HoT 框架3.3、Token 剪…

应用性能分析工具CPU Profiler

简介 本文档介绍应用性能分析工具CPU Profiler的使用方法&#xff0c;该工具为开发者提供性能采样分析手段&#xff0c;可在不插桩情况下获取调用栈上各层函数的执行时间&#xff0c;并展示在时间轴上。 开发者可通过该工具查看TS/JS代码及NAPI代码执行过程中的时序及耗时情况…

JDK安全剖析之安全处理入门

0.前言 Java 安全包括大量 API、工具以及常用安全算法、机制和协议的实现。Java 安全 API 涵盖了广泛的领域&#xff0c;包括加密、公钥基础设施、安全通信、身份验证和访问控制。Java 安全技术为开发人员提供了编写应用程序的全面安全框架&#xff0c;还为用户或管理员提供了…

WebSocketServer后端配置,精简版

首先需要maven配置 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.1.3.RELEASE</version></dependency> 然后加上配置类 这段代码是一个Spri…

Matlab中的参数定义

Matlab中的参数定义 文章目录 Matlab中的参数定义写在前面参数量验证实际使用数组有效性检查被检查数据类型有效数据类型有效属性举例说明文本有效性检查举例说明参考写在前面 Matlab是一种非类型化语言,大多数函数都不需要参数声明或验证。但是为了保证程序的通用性和按照预…

0204克拉默法则-矩阵及其运算-线性代数

含有n个未知数 x 1 , x 2 , ⋯ , x n x_1,x_2,\cdots,x_n x1​,x2​,⋯,xn​的n个线性方程的方程组 { a 11 x 1 a 12 x 2 ⋯ a 1 n x n b 1 , a 21 x 1 a 22 x 2 ⋯ a 2 n x n b 2 , ⋯ ⋯ , a n 1 x 1 a n 2 x 2 ⋯ a n n x n b n , \begin{cases} a_{11}x_1a_{1…

以Kotti项目为例使用pytest测试项目

在维护和构建大型项目时&#xff0c;单独一个一个手工测试代码已经不适用了&#xff0c;这时候就要用专门的测试框架进行测试。让我们以Kotti项目为例&#xff0c;用pytest这个测试框架进行实践测试吧。 使用python3.10 Ubuntu 系统 准备工作 下载和安装kotti库 pip install…

Flutter 解决NestedScrollView与TabBar双列表滚动位置同步问题

文章目录 前言一、需要实现的效果如下二、flutter实现代码如下&#xff1a;总结 前言 最近写flutter项目&#xff0c;遇到NestedScrollView与TabBar双列表滚动位置同步问题&#xff0c;下面是解决方案&#xff0c;希望帮助到大家。 一、需要实现的效果如下 1、UI图&#xff1…

代码随想录算法训练营三刷day46 | 动态规划之139.单词拆分

三刷day46 139.单词拆分1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp[i] 139.单词拆分 题目链接 解题思路&#xff1a;单词就是物品&#xff0c;字符串s就是背包&#xff0c;单词能否组成字符串s&#xff0c;就是问物品能不能把背包…

蓝桥杯-DS18B20温度传感器

一.管脚&芯片&寄存器 1.芯片 2.了解封装以及引脚的用法 3.相关寄存器 报警功能 二&#xff0c;如何使能DS18B20芯片 1.初始化芯片&比赛提供的驱动代码 比赛提供的底层驱动代码 /* # 单总线代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考…

【前沿模型解析】潜在扩散模 1 | LDM第一阶段-感知图像压缩总览

文章目录 0 开始~1 感知压缩的目的2 自回归编码器-解码器生成模型一览2.1 AE 自编码器2.2 VAE 变分自编码器2.3 VQ-VAE2.4 VQ-GAN 3 代码部分讲解总览 0 开始~ 从今天起呢&#xff0c;我们会剖析LDM&#xff08;潜在扩散模型&#xff09; 从去年开始&#xff0c;大量的生成模…

椋鸟数据结构笔记#7:堆排序、TopK

文章目录 堆排序堆排序的实现 TopK问题用堆实现TopK的时间复杂度TopK问题的实现 萌新的学习笔记&#xff0c;写错了恳请斧正。 堆排序 堆排序&#xff0c;就是利用堆的思想进行排序&#xff0c;是一种非常高效的排序方法。 它的基本思想是将待排序的序列构建成一个堆&#xf…

前端开发学习笔记4 (CSS三大特性、CSS盒子模型、CSS圆角边框、CSS盒子阴影、CSS文字阴影)

文章目录 CSS三大特性层叠性继承性优先级 CSS盒子模型网页布局的核心和过程盒子模型的组成盒子模型的边框盒子模型的内边距盒子模型的外边距 CSS圆角边框CSS盒子阴影CSS文字阴影 CSS三大特性 层叠性 基本概念&#xff1a;给相同的选择器设置了相同的样式&#xff0c;则此时一…