〇、简介

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. 基于机器人自主移动实现SLAM建图

    博客地址:https://www.cnblogs.com/zylyehuo/ 基于[移动机器人运动规划及运动仿真],详见之前的博客 移动机器人运动规划及运动仿真 - zylyehuo - 博客园 参考 ...

  2. ODOO13之五:Odoo 13开发之导入、导出以及模块数据

    大多数Odoo 模块的定义,如用户界面和安全规则,实际是存储在对应数据表中的数据记录.模块中的 XML 和 CSV 文件不是 Odoo 应用运行时使用,而是载入数据表的手段.正是因为这个原因,Odoo ...

  3. Qt+QtWebApp开发笔记(五):http服务器html中使用json触发ajax与后台交互实现数据更新传递

    前言   前面完成了页面的跳转.登录,很多时候不刷新页面就想刷新局部数据,此时ajax就是此种技术,且是异步的.  本篇实现网页内部使用js调用ajax实现异步交互数据.  在js中使用 ajax是通 ...

  4. NFS远程挂载

    NFS远程挂载 一.概述 NFS是一种基于TCP/IP 传输的网络文件系统协议.通过使用NFS协议,客户机可以像访问本地目录一样访问远程服务器中的共享资源 NAS存储: NFS服务的实现依赖于RPC ...

  5. Windows11右键菜单修改为Win10模式的方法

    Windows11右键菜单修改为Win10模式的方法 自述: 更新win11后看着鼠标右键的菜单有些不太舒服,索性就改回了win10的右键菜单的样式 , 下面开始进行操作 第一步 首先以管理员方式打开 ...

  6. Java猜数字,猜完一局以后,输入y继续下一次游戏,否则结束

    代码如下: public static void main(String[] args) { String x = ""; do { int random = (int) (Mat ...

  7. GGTalk 开源即时通讯系统源码剖析之:数据库设计

    自从<开源即时通讯GGTalk 8.0发布,增加Linux客户端,支持在统信UOS.银河麒麟上运行!>一文在博客园发布后,有园友联系我QQ,说能不能整理个更系统更详细地介绍GGTalk源码 ...

  8. 龙芯电脑编译redis (loongarch)

    1.获取源码 源码地址:https://redis.io/download/#redis-downloads 最新版本是7.2,这里用redis5测试,最后一个版本是5.0.14 wget https ...

  9. 规则引擎 ice

    目录 项目介绍 服务安装 创建数据库(MySQL) 下载安装 服务(启动.停止.重启) 打开后台 Client接入(Spring Boot) 示例 添加配置 新增 ICE liteflow 更适应我们 ...

  10. LSP协议被劫持,导致无法上网

    QQ无法登录,网页打不开 用火绒的断网修复 说已经修复了 结果屁用没有 然后找的百度经验 管理员打开命令行窗口 输入 netsh winsock reset catalog 重启即生效