什么是适配器模式?

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

为什么需要适配器模式?

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

适配器模式有哪些角色?

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. 33. 干货系列从零用Rust编写正反向代理,关于HTTP客户端代理的源码实现

    wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代 ...

  2. [CF1854E] Game Bundles

    题目描述 Rishi is developing games in the 2D metaverse and wants to offer game bundles to his customers. ...

  3. [NOI online22提高A] 丹钓战

    题目描述 有 \(n\) 个二元组 \((a_i, b_i)\),编号为 1 到 n. 有一个初始为空的栈 SS,向其中加入元素 \((a_i, b_i)\) 时,先不断弹出栈顶元素直至栈空或栈顶元素 ...

  4. flask蓝图(这玩意就是django的子应用)

    蓝图的概念类似django的子应用,作用就是分模块开发,有关联的都放在一起. 蓝图的创建步骤: 新建一个包(一个包就是一个模块.等同于一个子应用) 在包的__init__.py中创建蓝图对象 . 蓝图 ...

  5. pacman下载时经常出现Operation too slow. Less than 1 bytes/sec transferred the last 10 seconds

    问题 我在manjaro系统上使用pacman下载软件的时候,经常出现以下报错: 错误:无法从 mirrors.tuna.tsinghua.edu.cn : Operation too slow. L ...

  6. [活动(深圳)] .NET Love AI 之 .NET Conf China 2023 Party 深圳

    中国.NET 社区2023年12月16日 在北京成功举办了.NET Conf China 2023,虽然北京飘起雪,依然挡不住想要参加活动的全国各地的.NET开发兄弟姐妹的热情.大家可以通过大会精彩照 ...

  7. C# 在Word中添加Latex 数学公式和符号

    本篇内容介绍使用Spire.Doc for .NET在Word中添加Latex数学公式和符号的方法.编辑代码前,将Spire.Doc.dll文件添加引用至VS程序.dll文件包可通过官网下载导入(如果 ...

  8. 第五部分_Shell脚本条件判断语法结构

    条件判断语法结构 思考:何为真(true)?何为假(false)? 1. 条件判断语法格式 格式1: test条件表达式 格式2: [ 条件表达式 ] 格式3: [[ 条件表达式 ]] (支持正则~) ...

  9. 实战案例丨使用云连接CC和数据复制服务DRS实现跨区域RDS迁移和数据同步

    摘要:实践案例展示如何使用云连接CC和数据复制服务DRS实现跨区域RDS迁移和数据同步. [业务场景及诉求] 希望将不同区域"华北-北京四"的rds与"亚太-新加坡&qu ...

  10. makefile:带你了解一种常用于GNU gcc编译的工具语言

    摘要:该文章主要介绍makefile,一种常用语GNU gcc编译的工具语言,同时LiteOS也是利用该文件对工程项目进行make构建生成执行文件的. LiteOS源码中使用makefile进行文件的 ...