Adapter 适配器模式简介与 C# 示例【结构型1】【设计模式来了_6】

adapter,适配器,模式,简介,c#,示例,结构型,设计模式 · 浏览次数 : 266

小编点评

**简介** 适配器模式是一种结构型设计模式,用于将一个类的实现转换成另一种类的形式,使其与其他类的接口兼容。 **模式结构** * **客户端:**与特定数据源交互的类。 * **适配器:**将客户端与目标数据源的适配器。 * **目标数据源:**提供与客户端交互的接口的类。 **示例** ```csharp // IDataAdapter 接口 public interface IDataAdapter { // 数据填充方法 } // SqlDataAdapter 实现类 public sealed class SqlDataAdapter : IDataAdapter { // 数据填充方法 } // IAdapter 接口的适配器接口 public interface IAdapter { // 提供与目标数据源交互的方法 } ``` **用途** 适配器模式可以用于: * 将不同的数据源兼容性地使用相同的代码。 * 改进代码的可维护性和可扩展性。 * 将多个数据源合并到一个应用程序中。

正文

〇、简介

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】相似的内容:

Adapter 适配器模式简介与 C# 示例【结构型1】【设计模式来了_6】

关于 Adapter 适配器模式简介与 C# 示例。

软件设计模式系列之八——适配器模式

适配器模式(Adapter Pattern)是一种结构性设计模式,它允许将一个类的接口转换成客户端希望的另一个接口。适配器模式通常用于解决两个不兼容接口之间的兼容性问题,使得不同接口的类可以一起工作。这个模式涉及一个称为适配器的类,它充当两个不同接口之间的桥梁,使得它们可以协同工作。

(JAVA)设计模式-适配器模式

模式的定义和特点: 适配器模式(Adapter)是一种将一个类的接口转换成客户希望的另外一个接口的设计模式,可以提高代码的复用性和灵活性。 结构与实现: 定义一个适配器类来实现业务接口,再继承现有组件库中已经存在的组件。 示例: 创建业务接口类: 点击查看代码 public interface In

大模型高效微调详解-从Adpter、PrefixTuning到LoRA

一、背景 目前NLP主流范式是在大量通用数据上进行预训练语言模型训练,然后再针对特定下游任务进行微调,达到领域适应(迁移学习)的目的。 指令微调是预训练语言模型微调的主流范式 其目的是尽量让下游任务的形式尽量接近预训练任务,从而减少下游任务和预训练任务之间的Gap, 实现预训练语言模型适应下游任务,

C++编程英语词汇

abstract抽象的 abstraction抽象性、抽象件 access访问 access level访问级别 access function访问函数 adapter适配器 address地址 address-of operator取地址操作符 aggregation聚合 algorithm算法

SAM适配下游任务的探究:SAM Adapter

SAM-Adapter不仅显著提升了SAM的性能,而且在这些任务上达到了最先进的水平。

深入解读Prometheus Adapter:云原生监控的核心组件

本文详述了Prometheus Adapter的部署与配置,通过三个实践案例展示其在Kubernetes环境中的应用,帮助用户实现基于自定义指标的自动扩展和跨集群统一监控。 关注作者,分享AI全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验

[转帖]PCIe Switch Adapter:不只是NVMe HBA?

https://new.qq.com/rain/a/20200906A02YFF00 前几天有朋友提到,某款标称5400RPM(每分钟转数)的HDD硬盘,实际上是7200 RPM。今天又看到国外网站上用声音(噪声)测试来判断的方法。 由于对硬盘的感情,我本来也想就此写点东西,并且我还想提出另外2种更

k8s 自动扩缩容HPA原理及adapter配置详解👑

大家好,我是蓝胖子,都知道,k8s拥有自动扩缩容机制HPA,我们能够通过配置针对不同的扩缩容场景进行自动扩缩容,往往初学者在面对其中繁多配置的时候会学了又忘记,今天我将会以一种不同的视角,结合api server 请求 来探索这部分的配置,看完本篇,应该会对扩缩容这部分配置会有更深的理解。 自动扩缩

VirtualBox 下 CentOS7 静态 IP 的配置 → 多次踩坑总结,蚌埠住了!

开心一刻 一个消化不良的病人向医生抱怨:我近来很不正常,吃什么拉什么,吃黄瓜拉黄瓜,吃西瓜拉西瓜,怎样才能恢复正常呢? 医生沉默片刻:那你只能吃屎了 环境准备 VirtualBox 6.1 网络连接方式:桥接模式(Bridged Adapter) CentOS 7 精简版:CentOS-7-x86_