C#设计模式--适配器模式(Adapter Pattern)

适配器模式是一种 结构型设计模式,它允许不兼容的接口协同工作。通过创建一个适配器类来解决不同接口之间的不兼容问题,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

使用方式及用途

  1. 接口转换:将一个类的接口转换成客户端期望的另一个接口。
  2. 类适配器:通过继承目标接口和被适配者类来实现。
  3. 对象适配器:通过组合被适配者类来实现。

适配器模式在实际开发中有很多应用场景,主要适用于以下情况:
• 接口不兼容:需要将一个类的接口转换成客户端期望的另一个接口。
• 多平台支持:需要支持多个平台或框架,每个平台的接口不同。
• 扩展性:需要在不修改现有代码的情况下,增加新的功能或支持新的接口。

实现方式

继承或依赖:推荐使用依赖关系,而不是继承,以保持灵活性

结构

适配器模式包含以下几个主要角色:

目标接口(Target):定义客户需要的接口。
适配者类(Adaptee):定义一个已经存在的接口,这个接口需要适配。
适配器类(Adapter):实现目标接口,并通过组合或继承的方式调用适配者类中的方法,从而实现目标接口。

开发过程中的实际案例

案例1: 数据库适配器

假设一个应用程序,需要支持多种数据库(如 MySQL 和 SQLite)。我们可以使用适配器模式来适配不同的数据库驱动。
示例代码

目标接口(Target)

// 抽象数据库接口
public interface IDatabase
{void Connect(string connectionString);void ExecuteQuery(string query);
}

适配者类(Adaptee)


// MySQL 数据库实现
public class MySQLDatabase
{public void ConnectToMySQL(string connectionString){Console.WriteLine($"Connecting to MySQL database with connection string: {connectionString}");}public void ExecuteMySQLQuery(string query){Console.WriteLine($"Executing query on MySQL: {query}");}
}// SQLite 数据库实现
public class SQLiteDatabase
{public void ConnectToSQLite(string connectionString){Console.WriteLine($"Connecting to SQLite database with connection string: {connectionString}");}public void ExecuteSQLiteQuery(string query){Console.WriteLine($"Executing query on SQLite: {query}");}
}

适配器类(Adapter)

// MySQL 数据库适配器
public class MySQLDatabaseAdapter : IDatabase
{private readonly MySQLDatabase _mysqlDatabase;public MySQLDatabaseAdapter(MySQLDatabase mysqlDatabase){_mysqlDatabase = mysqlDatabase;}public void Connect(string connectionString){_mysqlDatabase.ConnectToMySQL(connectionString);}public void ExecuteQuery(string query){_mysqlDatabase.ExecuteMySQLQuery(query);}
}// SQLite 数据库适配器
public class SQLiteDatabaseAdapter : IDatabase
{private readonly SQLiteDatabase _sqliteDatabase;public SQLiteDatabaseAdapter(SQLiteDatabase sqliteDatabase){_sqliteDatabase = sqliteDatabase;}public void Connect(string connectionString){_sqliteDatabase.ConnectToSQLite(connectionString);}public void ExecuteQuery(string query){_sqliteDatabase.ExecuteSQLiteQuery(query);}
}

客户端代码

//创建客户端端
public class DatabaseClient
{private IDatabase _database;public DatabaseClient(IDatabase database){_database = database;}public void PerformOperations(){_database.Connect("connection_string");//数据库_database.ExecuteQuery("SELECT * FROM table");//随意一个表}
}// 使用示例
public class Program
{public static void Main(){MySQLDatabase mysqlDatabase = new MySQLDatabase();IDatabase mysqlAdapter = new MySQLDatabaseAdapter(mysqlDatabase);DatabaseClient clientForMySQL = new DatabaseClient(mysqlAdapter);clientForMySQL.PerformOperations();SQLiteDatabase sqliteDatabase = new SQLiteDatabase();IDatabase sqliteAdapter = new SQLiteDatabaseAdapter(sqliteDatabase);DatabaseClient clientForSQLite = new DatabaseClient(sqliteAdapter);clientForSQLite.PerformOperations();}
}

类图:

IDatabase
+void Connect(string connectionString)
+void ExecuteQuery(string query)
MySQLDatabase
+void ConnectToMySQL(string connectionString)
+void ExecuteMySQLQuery(string query)
SQLiteDatabase
+void ConnectToSQLite(string connectionString)
+void ExecuteSQLiteQuery(string query)
MySQLDatabaseAdapter
-MySQLDatabase _mysqlDatabase
+MySQLDatabaseAdapter(MySQLDatabase mysqlDatabase)
+void Connect(string connectionString)
+void ExecuteQuery(string query)
SQLiteDatabaseAdapter
-SQLiteDatabase _sqliteDatabase
+SQLiteDatabaseAdapter(SQLiteDatabase sqliteDatabase)
+void Connect(string connectionString)
+void ExecuteQuery(string query)
DatabaseClient
-IDatabase _database
+DatabaseClient(IDatabase database)
+void PerformOperations()
Program
+static void Main()

案例2:UI 控件适配器

假设一个需要支持多个平台(如 Windows 和 macOS),每个平台的 UI 控件接口不同。使用适配器模式来适配不同的 UI 控件。
示例代码

目标接口(Target)

// 抽象 UI 控件接口
public interface IButton
{void Render();void Click();
}

适配者类(Adaptee)

// Windows 按钮实现
public class WindowsButtonControl
{public void RenderWindowsButton(){Console.WriteLine("Rendering Windows Button");}public void ClickWindowsButton(){Console.WriteLine("Windows Button clicked");}
}// macOS 按钮实现
public class MacOSButtonControl
{public void RenderMacOSButton(){Console.WriteLine("Rendering macOS Button");}public void ClickMacOSButton(){Console.WriteLine("macOS Button clicked");}
}

适配器类(Adapter)

// Windows 按钮适配器
public class WindowsButtonAdapter : IButton
{private readonly WindowsButtonControl _windowsButtonControl;public WindowsButtonAdapter(WindowsButtonControl windowsButtonControl){_windowsButtonControl = windowsButtonControl;}public void Render(){_windowsButtonControl.RenderWindowsButton();}public void Click(){_windowsButtonControl.ClickWindowsButton();}
}// macOS 按钮适配器
public class MacOSButtonAdapter : IButton
{private readonly MacOSButtonControl _macOSButtonControl;public MacOSButtonAdapter(MacOSButtonControl macOSButtonControl){_macOSButtonControl = macOSButtonControl;}public void Render(){_macOSButtonControl.RenderMacOSButton();}public void Click(){_macOSButtonControl.ClickMacOSButton();}
}

客户端代码

public class UIController
{private IButton _button;public UIController(IButton button){_button = button;}public void ShowUI(){_button.Render();_button.Click();}
}// 使用示例
public class Program
{public static void Main(){WindowsButtonControl windowsButtonControl = new WindowsButtonControl();IButton windowsButtonAdapter = new WindowsButtonAdapter(windowsButtonControl);UIController controllerForWindows = new UIController(windowsButtonAdapter);controllerForWindows.ShowUI();MacOSButtonControl macosButtonControl = new MacOSButtonControl();IButton macosButtonAdapter = new MacOSButtonAdapter(macosButtonControl);UIController controllerForMacOS = new UIController(macosButtonAdapter);controllerForMacOS.ShowUI();}
}

类图:

IButton
+void Render()
+void Click()
WindowsButtonControl
+void RenderWindowsButton()
+void ClickWindowsButton()
MacOSButtonControl
+void RenderMacOSButton()
+void ClickMacOSButton()
WindowsButtonAdapter
-WindowsButtonControl _windowsButtonControl
+WindowsButtonAdapter(WindowsButtonControl windowsButtonControl)
+void Render()
+void Click()
MacOSButtonAdapter
-MacOSButtonControl _macOSButtonControl
+MacOSButtonAdapter(MacOSButtonControl macOSButtonControl)
+void Render()
+void Click()
UIController
-IButton _button
+UIController(IButton button)
+void ShowUI()
Program
+static void Main()

案例3. 文件读写适配器

假设程序需要支持多种文件格式(如 CSV 和 JSON),也可以使用适配器模式来适配不同的文件读写操作。
示例代码
目标接口(Target)

// 抽象日志记录接口
public interface ILogger
{void Log(string message);
}

适配者类(Adaptee)

// NLog 实现
public class NLog
{public void LogWithNLog(string message){Console.WriteLine($"Logging with NLog: {message}");}
}// Serilog 实现
public class Serilog
{public void LogWithSerilog(string message){Console.WriteLine($"Logging with Serilog: {message}");}
}

适配器类(Adapter)

// NLog 适配器
public class NLogAdapter : ILogger
{private readonly NLog _nlog;public NLogAdapter(NLog nlog){_nlog = nlog;}public void Log(string message){_nlog.LogWithNLog(message);}
}// Serilog 适配器
public class SerilogAdapter : ILogger
{private readonly Serilog _serilog;public SerilogAdapter(Serilog serilog){_serilog = serilog;}public void Log(string message){_serilog.LogWithSerilog(message);}
}

客户端代码

public class LoggerClient
{private ILogger _logger;public LoggerClient(ILogger logger){_logger = logger;}public void PerformLogging(){_logger.Log("This is a log message");}
}// 使用示例
public class Program
{public static void Main(){NLog nlog = new NLog();ILogger nlogAdapter = new NLogAdapter(nlog);LoggerClient clientForNLog = new LoggerClient(nlogAdapter);clientForNLog.PerformLogging();Serilog serilog = new Serilog();ILogger serilogAdapter = new SerilogAdapter(serilog);LoggerClient clientForSerilog = new LoggerClient(serilogAdapter);clientForSerilog.PerformLogging();}
}

类图:

ILogger
+void Log(string message)
NLog
+void LogWithNLog(string message)
Serilog
+void LogWithSerilog(string message)
NLogAdapter
-NLog _nlog
+NLogAdapter(NLog nlog)
+void Log(string message)
SerilogAdapter
-Serilog _serilog
+SerilogAdapter(Serilog serilog)
+void Log(string message)
LoggerClient
-ILogger _logger
+LoggerClient(ILogger logger)
+void PerformLogging()
Program
+static void Main()

优点

  1. 提高复用性:适配器模式可以使现有的类在新的环境中重用,而不需要修改原有类的代码。
  2. 增强灵活性:通过适配器,可以轻松地将不同的类集成在一起,即使它们的接口不兼容。
  3. 开放封闭原则:符合开放封闭原则,即对扩展开放,对修改封闭。可以通过添加新的适配器类来支持新的接口,而不需要修改现有代码。

缺点

  1. 增加复杂性:适配器模式会增加系统的复杂性,因为需要引入额外的适配器类。
  2. 性能开销:适配器模式可能会引入额外的性能开销,特别是在适配器类中进行大量转换和处理时。
  3. 维护成本:随着适配器数量的增加,维护这些适配器类的成本也会增加。

总结

适配器模式是一种非常实用的设计模式,特别适用于需要将不同接口的类集成在一起的场景。通过适配器模式,可以有效地解决接口不兼容的问题,提高代码的复用性和灵活性。然而,使用适配器模式也会增加系统的复杂性和维护成本,因此在实际开发中需要权衡利弊,合理使用。

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

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

相关文章

西部地区生活物资保供与城郊大仓基地高质量建设运营论坛西安市成功举办

2024 年 12 月 5日,由中国商业联合会、陕西省商务厅指导,中国商业联合会商贸物流与供应链分会、西安市发改委、西安市商务局主办,中企盟(北京)电商物流技术研究院、西安商业联合会、陕西省商贸物流供应链协会承办的“西…

[笔记] Windows 上 Git 安装详细教程:从零开始,附带每个选项解析

Git 是目前最流行的分布式版本控制系统之一,广泛应用于软件开发和项目管理中。对于 Windows 用户来说,正确安装和配置 Git 是开始使用 Git 的第一步。本文提供一份详细的指南,帮助你在 Windows 系统上顺利安装 Git,并解释每个安装…

五天SpringCloud计划——DAY3之服务治理(Nacos+OpenFeign+OKHttp)

一、引言 在微服务架构中,一个项目通常会被分为多个模块来降低耦合,但是通常情况下,一个项目中总会出现一种情况——一个模块内的方法需要调用另一个模块内的方法。本文就来使用NacosOpenFeignOKHttp帮助大家解决这个问题。 二、Nacos的使用…

go-blueprint create exit status 1

1. 异常信息 2024/12/06 10:59:19 Could not initialize go.mod in new project exit status 1 2024/12/06 10:59:19 Problem creating files for project. exit status 1 Error: exit status 12. 排查思路 手动进行go mod init查看手动的报错解决报错 3. 解决问题 发现是GO11…

Socket编程-tcp

1. 前言 在tcp套接字编程这里,我们将完成两份代码,一份是基于tcp实现普通的对话,另一份加上业务,client输入要执行的命令,server将执行结果返回给client 2. tcp_echo_server 与udp类似,前两步&#xff1…

Python使用Selenium自动实现表单填写之蛇年纪念币蛇钞预约(附源码,源码有注释解析,已测试可用

Python实现纪念币预约自动填写表单 声明:本文只做技术交流,不可用代码为商业用途,文末有源码下载,已测试可用。 Part 1 配置文件改写(源码 有详细的注释说明 读取配置文件,自己组数据库,录入信息 配置文件 Part 2 主函数 每一期的xpath路径都不一样 所以需要提前去网站…

【计算机网络】期末速成(2)

部分内容来源于网络,侵删~ 第五章 传输层 概述 传输层提供进程和进程之间的逻辑通信,靠**套接字Socket(主机IP地址,端口号)**找到应用进程。 传输层会对收到的报文进行差错检测。 比特流(物理层)-> 数据帧(数据链路层) -> 分组 / I…

Vue3网站锚点定位

网站上实现锚点定位的方法有很多&#xff0c;今天介绍vue3实现的定位效果的方式。通过scrollIntoViewh函数的行为&#xff0c;滑动至指定的容器。 一、样式布局 <template> <div style"width: 100%; display: flex;flex-direction: column;"><div …

微信小程序实现图片拖拽调换位置效果 -- 开箱即用

在编写类似发布朋友圈功能的功能时&#xff0c;需要实现图片的拖拽排序&#xff0c;删除图片等功能。 一、效果展示 **博主的小程序首页也采用了该示例代码&#xff0c;可以在威信中搜索&#xff1a;我的百宝工具箱 二、示例代码 1.1、在自己的小程序中创建组件 1.2、组件…

五、docker的网络模式

五、docker的网络模式 5.1 Docker的四种网络模式 当你安装docker时&#xff0c;它会自动创建三个网络&#xff0c;可使用如下命令查看&#xff1a; [rootlocalhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 7390284b02d6 bridge bridge lo…

ros项目dual_arm_pick-place(对比moveit配置助手生成的文件)

目录 前言正文gazebo_controllers.yaml变更ros_controllers.yaml变更simple_moveit_controllers.yaml变更moveit_planning_execution.launch变更ros_controllers.launch变更其他文件 汇总总结 前言 在本专栏前文中讲到&#xff0c;作者有moveit配置助手导出的包marmbots&#…

【uni-app 微信小程序】新版本发布提示用户进行更新

知识准备 uni.getUpdateManager文档介绍 不支持APP与H5&#xff0c;所以在使用的时候要做好平台类型的判断&#xff0c;如何判断&#xff0c;参考条件编译处理多端差异 代码参考 export const updateApp () > {const updateManager uni.getUpdateManager()updateManag…

Java-操作xls替换文本或图片

准备xls模板文件&#xff1a;template.xls 要求根据不同的产品型号和图片&#xff0c;插入到模板文件中&#xff0c;然后再填充产品信息。 准备需要替换的图片和数据 功能实现 package net.work.controller.base;import io.swagger.annotations.Api; import io.swagger.annot…

.Net学习

1 什么是.NET Core .NET是开发平台&#xff0c;.NET Framework、.NET Core、Xamaarin/Mono的统称。 .NET Framework是只能在Windows上开发的技术 .NET Core是可以跨平台开发的技术 Xamaarin/Mono是移动端开发的技术 .NET Core&#xff1a;跨平台、免费、开源&#xff0c;可…

半监督学习与数据增强

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

【成功解决:Can‘t uninstall ‘ultralytics‘. No files were found to uninstall.】

问题&#xff1a; 尝试卸载ultralytics时&#xff0c;使用pip uninstall ultralytics命令&#xff0c;已经卸载了ultralytics&#xff0c;但是仍出现Cant uninstall ultralytics. No files were found to uninstall&#xff0c;导致无法卸载干净。 原因 ultralytics相应的dis…

AcWing 3496. 特殊年份

文章目录 前言代码思路 前言 写简单题没啥。反正都是要写的&#xff0c;先把能拿到的分数拿了&#xff0c;之后有机会再去啃一啃硬骨头。啃不下来就算了。 代码 #include<bits/stdc.h> using namespace std; char a1[10],a2[10],a3[10],a4[10],a5[10]; int main(){cin…

MongoDB性能监控工具

mongostat mongostat是MongoDB自带的监控工具&#xff0c;其可以提供数据库节点或者整个集群当前的状态视图。该功能的设计非常类似于Linux系统中的vmstat命令&#xff0c;可以呈现出实时的状态变化。不同的是&#xff0c;mongostat所监视的对象是数据库进程。mongostat常用于…

【LeetCode: 999. 可以被一步捕获的棋子数 + 模拟】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

智创 AI 新视界 -- 优化 AI 模型训练效率的策略与技巧(16 - 1)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…