什么是适配器模式?

适配器模式是一种结构型设计模式,用于将现有接口转换为符合客户端期望的接口。适配器模式允许不兼容的类可以相互协作。

为什么需要适配器模式?

在实际开发中,经常会遇到需要复用一些已有的类,但是这些类的接口和我们当前需要的接口不匹配的情况。而适配器模式就可以让这些不兼容的类之间可以协作,方便地进行复用。

适配器模式有哪些角色?

1. 目标接口(Target):期望得到的接口,客户端调用的接口。
2. 原始类(Adaptee):现有的需要进行适配的接口。
3. 适配器(Adapter):将原始类的接口转换成了目标接口的类。

适配器模式的基本流程是什么?

1. 客户端通过调用 Target 接口中的方法,请求完成某个功能。
2. 适配器内部包装了一个 Adaptee 实例,并实现了 Target 接口。
3. 客户端调用适配器的方法,适配器实际上会调用 Adaptee 实例的方法。
4. 适配器将结果转换为目标接口对应的格式,返回给客户端。

适配器模式的优点是什么?

1. 提高代码的复用性,将原有的类适配到新的接口上之后可以在新的系统中重复使用。
2. 降低了类之间的耦合度,使用适配器模式可以让原有的类和新的系统之间解耦。
3. 提高了系统的灵活性和可扩展性,将来如果需要增加其他的接口类型,只需要增加相应的适配器即可。

适配器模式的缺点是什么?

1. 适配器模式增加了系统的复杂性,需要增加额外的适配器类来完成接口转换工作。
2. 适配器模式可能会造成一定的性能损失,因为需要增加额外的适配器层来完成数据转换。

适配器模式有哪些应用场景?

1. 系统需要使用现有的类,而这些类的接口不符合系统的需要。
2. 统一输入/输出接口,如日志记录、数据统计等。
3. 兼容性问题,如不同操作系统、不同数据库之间的数据交换。

总结一下适配器模式五个W和一个H:

- What:适配器模式,一种结构型设计模式,将不兼容的接口转换为符合客户端期望的接口。
- Why:用于复用现有的类,并让不兼容的接口之间可以进行协作。
- Who:目标接口、原始类、适配器。
- When:需要将一些不兼容的类适配到新的接口上,从而让它们可以在新系统中被重复使用。
- Where:适配器模式常用于统一输入/输出接口、解决兼容性问题等场景。
- How:客户端通过调用适配器的方法,适配器实际上会调用原始类的方法,并将结果转换为目标接口对应的格式后返回给客户端。

目标角色

    public interface IHelper
{
void Add<T>();
void Delete<T>();
void Update<T>();
void Query<T>();
}

被适配器角色

sqlserver、mysql、redis

适配器角色

SqlServerHelper
    public class SqlServerHelper : IHelper
{
public void Add<T>()
{
Console.WriteLine("This is {0} Add", this.GetType().Name);
}
public void Delete<T>()
{
Console.WriteLine("This is {0} Delete", this.GetType().Name);
}
public void Update<T>()
{
Console.WriteLine("This is {0} Update", this.GetType().Name);
}
public void Query<T>()
{
Console.WriteLine("This is {0} Query", this.GetType().Name);
}
}
MysqlHelper
    public class MysqlHelper : IHelper
{
public void Add<T>()
{
Console.WriteLine("This is {0} Add", this.GetType().Name);
}
public void Delete<T>()
{
Console.WriteLine("This is {0} Delete", this.GetType().Name);
}
public void Update<T>()
{
Console.WriteLine("This is {0} Update", this.GetType().Name);
}
public void Query<T>()
{
Console.WriteLine("This is {0} Query", this.GetType().Name);
}
}

对于一些第三方的组件方法,它里面已有类似的方法,这个时候我们可以采取 继承或 组合的方式,来做适配

    /// <summary>
/// 第三方提供的 openstack servicestack
/// 不能修改
/// </summary>
public class RedisHelper
{
public RedisHelper()
{
Console.WriteLine($"构造RedisHelper");
}
public void AddRedis<T>()
{
Console.WriteLine("This is {0} Add", this.GetType().Name);
}
public void DeleteRedis<T>()
{
Console.WriteLine("This is {0} Delete", this.GetType().Name);
}
public void UpdateRedis<T>()
{
Console.WriteLine("This is {0} Update", this.GetType().Name);
}
public void QueryRedis<T>()
{
Console.WriteLine("This is {0} Query", this.GetType().Name);
}
}

类适配器,通过继承的方式,在它上面实现目标IHelper

    /// <summary>
/// 类适配器
/// </summary>
public class RedisHelperInherit : RedisHelper, IHelper
{
public RedisHelperInherit()
{
Console.WriteLine($"构造{this.GetType().Name}");
} public void Add<T>()
{
base.AddRedis<T>();
} public void Delete<T>()
{
base.DeleteRedis<T>();
} public void Query<T>()
{
base.QueryRedis<T>();
} public void Update<T>()
{
base.UpdateRedis<T>();
}
}

对象适配器,通过组合的方式,在它上面实现目标IHelper

    public class RedisHelperObject : IHelper
{
public RedisHelperObject()
{
Console.WriteLine($"构造{this.GetType().Name}");
}
//属性注入 声明写死
private RedisHelper _RedisHelper = new RedisHelper(); ////构造函数 可以替换(需要抽象)
public RedisHelperObject(RedisHelper redisHelper)
{
this._RedisHelper = redisHelper;
} ////方法注入 可以替换(需要抽象)
public void SetObject(RedisHelper redisHelper)
{
this._RedisHelper = redisHelper;
} public void Add<T>()
{
this._RedisHelper.AddRedis<T>();
} public void Delete<T>()
{
this._RedisHelper.DeleteRedis<T>();
} public void Query<T>()
{
this._RedisHelper.QueryRedis<T>();
} public void Update<T>()
{
this._RedisHelper.UpdateRedis<T>();
}
}

运行测试

            {
//继承 既满足现有的规范调用,又没有修改RedisHelper
//类适配器模式
IHelper helper = new RedisHelperInherit();
helper.Add<Program>();
helper.Delete<Program>();
helper.Update<Program>();
helper.Query<Program>();
}
{
//组合 既满足现有的规范调用,又没有修改RedisHelper
//对象适配器
IHelper helper = new RedisHelperObject();
helper.Add<Program>();
helper.Delete<Program>();
helper.Update<Program>();
helper.Query<Program>();
}

源码下载:https://gitee.com/weilong2020/csharp_23_-design-patterns.git

C#设计模式06——适配器的写法的更多相关文章

  1. 设计模式C++描述----06.适配器(Adapter)模式

    一. 定义 适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. Adapter 模式的两种类别:类模式和对象模式. 二. 举例说明 实际中 ...

  2. Java设计模式06:常用设计模式之适配器模式(结构型模式)

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

  3. 设计模式模式适配器(Adapter)摘录

    23种子GOF设计模式一般分为三类:创建模式.结构模型.行为模式. 创建模式抽象的实例,他们帮助建立一个系统,是独立于如何.这是一个这些对象和陈述的组合.创建使用继承一个类架构更改实例,一个对象类型模 ...

  4. Android 设计模式模式适配器

    自定义适配器模式:一类的接口,转换成客户的期望,也是一个接口.适配器使原本接口不是与类兼容可以无缝.下面两个图看起来更加清晰 watermark/2/text/aHR0cDovL2Jsb2cuY3Nk ...

  5. 架构设计之设计模式 (一) 适配器(Adapter)---提高复用性

    简介 简介是为了描述一下该模式是干嘛用的,为了让不了解该模式的人看了之后也有一些新的认识. 本文章分为两部分,第一部分主要介绍适配器模式:第二部分介绍该模式与相近模式的异同. 下午一直在讨论设计模式, ...

  6. Java设计模式之适配器设计模式(项目升级案例)

    今天是我学习到Java设计模式中的第三个设计模式了,但是天气又开始变得狂热起来,对于我这个凉爽惯了的青藏人来说,又是非常闹心的一件事儿,好了不管怎么样,目标还是目标(争取把23种Java设计模式接触一 ...

  7. PHP设计模式系列 - 适配器

    什么是适配器: 适配器设计模式只是将某个对象的接口适配为另一个对象所期望的接口. 设计情景: 假如我们原始的有一个UserInfo的类,提供用户信息的类,早起设计该类的时候,只实现了一个getUser ...

  8. 设计模式06: Adapter 适配器模式(结构型模式)

    Adapter 适配器模式(结构型模式) 适配(转换)的概念无处不在:电源转接头.电源适配器.水管转接头... 动机(Motivation)在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象 ...

  9. Java设计模式之适配器设计模式

    1.适配器模式( Adapter)定义将一个类的接口转换成客户希望的另外一个接口.Adapter 模式使得原来由于接口不兼容而不能一起工作的 那些类可以一起工作. 现实案例如下:  墙上电源类(22 ...

  10. 设计模式------Adapter(适配器)

    地址:http://blog.csdn.net/wuzhekai1985/article/details/6665542,仅供学习用. 适配器:STL实现了一种数据结构,称为双端队列(deque),支 ...

随机推荐

  1. TCP连接断开:为什么要挥手四次

    本文分享自华为云社区<解密TCP连接断开:四次挥手的奥秘和数据传输的安全>,作者: 努力的小雨 . TCP 连接断开 在当今数字化时代,互联网已经成为了人们生活中不可或缺的一部分.而在互联 ...

  2. Android阅读器之文本、图片和表格测量

    文章摘要 本文将介绍如何在Android开发中实现文本.图片和表格的测量.我们将使用Android Studio和Java语言,并利用Android SDK中的相关类库. 正文 文本测量 在Andro ...

  3. 华企盾DSC服务器状态显示“服务未安装”

    在cmd中先删除原服务:sc delete DSEServer 然后重新创建DSEServer所在位置:sc create "DSEServer" binpath= "C ...

  4. 聊聊流式数据湖Paimon(二)

    当前的问题 Apache Paimon 最典型的场景是解决了 CDC (Change Data Capture) 数据的入湖:CDC 数据来自数据库.一般来说,分析需求是不会直接查询数据库的. 容易对 ...

  5. 【Python】【OpenCV】绘制外接矩形、外接圆

    外接矩形.外接圆: 1 import cv2 2 import numpy 3 4 img = cv2.imread('../img/img.png', -1) 5 ret, thresh = cv2 ...

  6. OpenEuler22.03安装最新版本Docker

    一.环境及问题 操作系统环境如下: 操作系统:OpenEuler 22.03 LTS 安装方式:最小化安装 在操作系统安装完毕如果直接采用dnf或者yum方式安装docker: sudo dnf in ...

  7. springboot整合apollo配置中心

    springboot整合apollo配置中心 springboot整合apollo配置中心官网文档说明得比较清楚,但还是有一些坑注意的. 官网文档:https://www.apolloconfig.c ...

  8. 2023-11-01:用go语言,沿街有一排连续的房屋。每间房屋内都藏有一定的现金, 现在有一位小偷计划从这些房屋中窃取现金, 由于相邻的房屋装有相互连通的防盗系统,所以小偷 不会窃取相邻的房屋, 小

    2023-11-01:用go语言,沿街有一排连续的房屋.每间房屋内都藏有一定的现金, 现在有一位小偷计划从这些房屋中窃取现金, 由于相邻的房屋装有相互连通的防盗系统,所以小偷 不会窃取相邻的房屋, 小 ...

  9. 文心一言 VS 讯飞星火 VS chatgpt (18)-- 算法导论4.1 5题

    五.使用如下思想为最大子数组问题设计一个非递归的.线性时间的算法.从数组的左边界开始,由左至右处理,记录到目前为止已经处理过的最大子数组.若已知 A[1..j]门的最大子数组,基于如下性质将解扩展为 ...

  10. 教你几个部署多个nginx-ingress的注意事项

    本文分享自华为云社区<nginx-ingress工作原理以及多nginx-ingress部署注意事项>,作者: 可以交个朋友. 一.nginx-ingress工作原理 nginx-ingr ...