〇、简介

1、什么是适配器模式?

一句话解释:

  两个无关联的类,通过实现同一接口或继承对方得到新的适配器类,新的适配器类中通过实现原本类的操作,可达到进行相同的操作的目的。

适配器模式(Apapter Pattern)是一种结构型设计模式,用于将一个类的实现转换成客户端所期望的另一个类,这个类中的操作和目标类具有相同的操作,以达到两个不相关的类可以互操作的目的。

官方意图:将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

 一个比喻:(两位来自不同方言区的学生)

  分别来自广州和海口的两位同学,如果都各自说自己的家乡话粤语和海南话,则根本无法沟通,此时普通话就是一个适配器,将两种方言翻译成普通话来进行适配,这样就可以顺畅沟通了。

2、优缺点和使用场景

优缺点:

  • 通过适配器模式,可以使两个不兼容的接口协同工作,避免了修改现有代码的需要。
  • 提高了代码的复用性和灵活性,因为适配器可以重复使用,并且可以在不同的场景中使用。
  • 降低了系统的耦合度,适配器模式允许系统中的各个组件相互独立地演化。
  • 由于引入了适配器类,可能造成系统的复杂度增加。
  • 在某些情况下,可能需要创建多个适配器来满足不同的客户端需求。

适用场景:

  • 当需要使用一个已经存在的类,但其接口与你的需求不兼容时,可以使用适配器模式。
  • 当想要创建一个可复用的类,该类与一些不相关或不可预见的类进行交互时,适配器模式也是很有用的。
  • 当希望通过一个统一的接口与多个类进行交互时,适配器模式可以提供一个统一的接口。
  • 当需要在不破坏现有代码结构的情况下,对已有的类进行功能扩展时,可以考虑使用适配器模式。

实际使用场景举例:

  • 旧系统与新系统的兼容:当需要将一个旧系统的接口适配成一个新系统可以使用的接口时,适配器模式非常有用。通过创建一个适配器类,可以使新系统能够无缝地与老旧系统进行通信,而不需要修改新系统的代码。
  • 第三方组件的集成:当我们需要使用某个第三方组件,但其提供的接口与我们的系统需求不一致时,可以使用适配器模式。适配器可以将第三方组件的接口转换为符合我们系统需求的接口形式,从而能够顺利地集成到我们的系统中。
  • 多个类库之间的互操作:当我们需要在多个类库之间进行互操作,但它们之间的接口不兼容时,适配器模式可以起到桥梁的作用。通过创建适配器类,将不同类库的接口转换为统一的接口,实现它们之间的互操作性。
  • 接口的标准化:当系统中存在多个类似但接口不同的组件时,可以使用适配器模式将它们的接口标准化。通过适配器,这些组件可以统一使用相同的接口,从而提高系统的一致性和可维护性。
  • 对已有类的功能扩展:当我们需要对一个已有的类进行功能扩展时,可以使用适配器模式。通过创建适配器类,将新功能与原有类进行适配,使得原有类能够使用新功能,同时不影响原有代码的稳定性。

一、通过示例简单实现

下面是一个使用适配器设计模式的示例,假设我们有一个电源插座接口 ISocket,其中定义了供电方法 SupplyPower():

class Program // 测试
{
static void Main(string[] args)
{
// 国标插座
ChinaSocket chinaSocket = new ChinaSocket();
ChinaSocketAdapter chinaAdapter = new ChinaSocketAdapter(chinaSocket);
Laptop laptop1 = new Laptop(chinaAdapter); // 笔记本1 通过国标版插座充电
laptop1.Charge();
// 美版插座
USASocket usaSocket = new USASocket();
USASocketAdapter usaAdapter = new USASocketAdapter(usaSocket);
Laptop laptop2 = new Laptop(usaAdapter); // 同一类型的笔记本2 通过美标版插座充电
laptop2.Charge();
Console.ReadKey();
}
}
// 电源插座接口
public interface ISocket
{
void SupplyPower();
}
// 国标版插口
public class ChinaSocket
{
public string name { get; set; }
public void Charge()
{
Console.WriteLine("开始充电!");
}
}
// 美版插口
public class USASocket
{
public string name { get; set; }
public void PowerUp()
{
Console.WriteLine("Start charging!");
}
}
// 国标版的适配器,实现统一的电源插座接口
public class ChinaSocketAdapter : ISocket
{
private readonly ChinaSocket _chinaSocket;
public ChinaSocketAdapter(ChinaSocket chinaSocket)
{
_chinaSocket = chinaSocket;
}
public void SupplyPower() // 国标版实现充电方法,调用特有的 Charge() 方法
{
_chinaSocket.Charge();
}
}
// 美版插座适配器,实现统一的插座接口
public class USASocketAdapter : ISocket
{
private readonly USASocket _usaSocket;
public USASocketAdapter(USASocket usaSocket)
{
_usaSocket = usaSocket;
}
public void SupplyPower() // 美版实现充电方法,调用特有的 PowerUp() 方法
{
_usaSocket.PowerUp();
}
}
// 笔记本电脑类实现,统一充电方法 Charge()
public class Laptop
{
private readonly ISocket _socket;
public Laptop(ISocket socket)
{
_socket = socket;
}
public void Charge()
{
_socket.SupplyPower();
}
}

最终,无论是国标还是美版的插座,均调用 Charge() 方法进行充电,充当适配器角色的就是电源插座接口 IScoket。

二、适配器模式的结构

如下简单画一下上一章节示例代码对应的类图:(美版相似就省略了,只显示国标版)

Client:给 Laptop 声明插座并完成充电动作。

Laptop:定义统一充电接口的模板,供适配器实现。

ChinaSocketAdapter:对 ChinaSocket 类和 Laptop 进行适配。

ChinaSocket:已存在的类,此类需要适配。

三、适配器模式在 .Net Core 中的实际应用

IDataAdapter 接口的实现类通常是数据库访问器,它们提供了一种与特定数据库类型无关的方式来访问数据。

下面是接口 IDataAdapter 的源码:

// System.Data.Common, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// System.Data.IDataAdapter
using System.Data;
using System.Diagnostics.CodeAnalysis; public interface IDataAdapter
{
MissingMappingAction MissingMappingAction { get; set; } MissingSchemaAction MissingSchemaAction { get; set; } ITableMappingCollection TableMappings { get; } [RequiresUnreferencedCode("IDataReader's (built from adapter commands) schema table types cannot be statically analyzed.")]
DataTable[] FillSchema(DataSet dataSet, SchemaType schemaType); int Fill(DataSet dataSet); IDataParameter[] GetFillParameters(); [RequiresUnreferencedCode("IDataReader's (built from adapter commands) schema table types cannot be statically analyzed.")]
int Update(DataSet dataSet);
}

具体的数据库,均实现了 IDataAdapter 接口:

// SQL Server
public sealed class SqlDataAdapter : DbDataAdapter, IDataAdapter, IDbDataAdapter, ICloneable
{ ... }
// Oracle
[Designer("Oracle.VsDevTools.OracleVSGDataAdapterWizard, Oracle.VsDevTools, Version=4.122.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=MSIL", typeof(IDesigner))]
[ToolboxBitmap(typeof(resfinder), "Oracle.ManagedDataAccess.src.Client.Icons.OracleDataAdapterToolBox_hc.bmp")]
[DefaultEvent("RowUpdated")]
public sealed class OracleDataAdapter : DbDataAdapter, IDbDataAdapter, IDataAdapter
{ ... }
// MySQL
[DesignerCategory("Code")]
[Designer("MySql.Data.MySqlClient.Design.MySqlDataAdapterDesigner,MySqlClient.Design")]
public sealed class MySqlDataAdapter : DbDataAdapter, IDbDataAdapter, IDataAdapter
{ ... }

通过使用 IDataAdapter 接口,我们可以编写与特定数据库类型无关的代码,而只需要关心数据集的结构和操作。这样,我们就可以更轻松地更换或扩展我们的数据源,而不需要修改应用程序的代码。同时,IDataAdapter 接口还支持数据映射和数据验证等高级功能,使得我们可以更好地处理复杂的数据操作。

四、相关模式

桥接模式(Bridge)的结构与对象适配器类似,但是 Bridge 模式的出发点不同。Bridge 的目的是将接口部分和实现部分分离,从而可以对它们较为容易也相对独立地加以改变。而 Adapter  则意味着改变一个已有对象的接口。

装饰模式(Decorator)增强了其他对象的功能而同时又不改变它的接口,因此 Decorator 对应用程序的透明性比适配器要好。结果是 Decorator 支持递归组合,而纯粹使用适配器是不可能实现这一点的。

代理模式(Proxy)在不改变它的接口的条件下,为另一个对象定义了一个代理。

Adapter 适配器模式简介与 C# 示例【结构型1】【设计模式来了_6】的更多相关文章

  1. C#设计模式之七适配器模式(Adapter)【结构型】

    一.引言   从今天开始我们开始讲[结构型]设计模式,[结构型]设计模式有如下几种:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式.[创建型]的设计模式解决的是对象创建的问题, ...

  2. C#设计模式之六适配器模式(Adapter Pattern)【结构型】

    一.引言 从今天开始我们开始讲[结构型]设计模式,[结构型]设计模式有如下几种:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式.[创建型]的设计模式解决的是对象创建的问题,那[ ...

  3. C++ 设计模式 3:结构型模式

    0 结构型模式 让类和类进行组合,获得更大的结构,获得新功能的方式. 1 代理模式 Proxy 模式又被叫做代理模式,是结构型的设计模式之一,它可以 为其他对象提供一种代理以控制对这个对象的访问. 所 ...

  4. (Java)设计模式:结构型

    前言 这篇博文续接的是 UML建模.设计原则.创建型设计模式.行为型设计模式,有兴趣的可以看一下 3.3.结构型 这些设计模式关注类和对象的组合.将类和对象组合在一起,从而形成更大的结构 * 3.3. ...

  5. 面向对象程序设计(OOP设计模式)-结构型模式之装饰器模式的应用与实现

    课程名称:程序设计方法学 实验4:OOP设计模式-结构型模式的应用与实现 时间:2015年11月18日星期三,第3.4节 地点:理1#208 一.实验目的 加深对结构型设计模式的理解以及在开发中的实际 ...

  6. Go语言实现的23种设计模式之结构型模式

    摘要:本文主要聚焦在结构型模式(Structural Pattern)上,其主要思想是将多个对象组装成较大的结构,并同时保持结构的灵活和高效,从程序的结构上解决模块之间的耦合问题. 本文分享自华为云社 ...

  7. C#设计模式之十一外观模式(Facade)【结构型】

    一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...

  8. C#设计模式之十三代理模式(Proxy)【结构型】

    一.引言   今天我们要讲[结构型]设计模式的第七个模式,也是"结构型"设计模式中的最后一个模式,该模式是[代理模式],英文名称是:Proxy Pattern.还是老套路,先从名字 ...

  9. C#设计模式之十外观模式(Facade Pattern)【结构型】

    一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...

  10. C#设计模式之十二代理模式(Proxy Pattern)【结构型】

    一.引言 今天我们要讲[结构型]设计模式的第七个模式,也是“结构型”设计模式中的最后一个模式,该模式是[代理模式],英文名称是:Proxy Pattern.还是老套路,先从名字上来看看.“代理”可以理 ...

随机推荐

  1. 顶会ICSE-2023发布LIBRO技术,利用大模型技术进行缺陷重现,自动重现率达33%

    摘要:本文围绕LIBRO技术的主要步骤进行介绍. 本文分享自华为云社区<[LLM for SE]顶会ICSE-2023发布LIBRO技术,利用大模型技术进行缺陷重现,自动重现率(33%)实现业界 ...

  2. linux 引导过程和服务控制

    目录 一.引导分区 二.服务控制 三.运行级别 四.systemd初始化 五.模拟错误 一.引导分区 原理:引导分区是指在开机启动到进入系统这之间的过程 引导分区的过程:1.开机自检 自检顺序:BIO ...

  3. OWASP移动应用安全测试指南中文版

    OWASP移动应用安全测试指南(MASTG)是OWASP移动应用安全(MAS)旗舰项目的一部分,是一本涵盖移动应用安全分析过程.技术和工具的综合手册,也是一套详尽的测试案例,用于验证OWASP移动应用 ...

  4. Docker 镜像命令

    Docker 镜像命令 1.Docker images--列出本地镜像 命令:docker images [OPTIONS] [REPOSITORY[:TAG]] 选项 -a :列出本地所有的镜像(含 ...

  5. QQ 邮箱设置自定义域名邮箱

    编者有话说 这篇文章来源于2019年12月左右,我在配置 Galaxy 生信分析平台的邮件服务过程中的一个尝试,我最早把它记录在了语雀上面,但由于某些原因一直迟迟没有更新到生信科技爱好者的公众号.直至 ...

  6. 体验了一把 MiniGPT-4,一言难尽

    最近看到一个好玩的开源项目:MiniGPT-4. 看名字像 GPT-4 的小老弟,其实没啥关系. 简单说,它可以识别图像,基于图像你可以和它对话,它能生成图片描述.网站.诗歌. 先看看官方给出的例子截 ...

  7. Journal of Electronic Imaging投稿分享

    Journal of Electronic Imaging投稿分享 在研究生阶段中的第一篇论文,前后总共三个月,还是很开心的!!! 附下中稿图片 这个期刊从二月份开始投的,然后三月份给了大修,大修时间 ...

  8. 【了解LLM】——LoRA

    本文地址:https://www.cnblogs.com/wanger-sjtu/p/17470327.html 论文链接:link code: github 什么是LoRA LoRA,英文全称Low ...

  9. Mysql 5.7 的安装

    Mysql的安装 1 windows两种安装方式,入门选手推荐第二种(win10演示) Mysql官网下载地址:https://dev.mysql.com/downloads/mysql/ 2 开始准 ...

  10. Docker 中的 .NET 异常了怎么抓 Dump

    一:背景 1. 讲故事 有很多朋友跟我说,在 Windows 上看过你文章知道了怎么抓 Crash, CPU爆高,内存暴涨 等各种Dump,为什么你没有写在 Docker 中如何抓的相关文章呢?瞧不上 ...