首页 > 编程语言 >c#中适配器模式详解

c#中适配器模式详解

时间:2023-09-26 15:00:28浏览次数:45  
标签:c# 适配器 三孔 接口 插座 两孔 public 详解

基础介绍:

  想象这样一个场景,原项目中接口返回的数据是XML格式的数据,但现在来了一个新客户,它期望接口返回的数据类型为json格式的。

  想要实现要么就是改原有接口,但这样就违反了开闭原则,容易出现未知bug,影响到老客户的正常使用。

  而如果写一个适配器类也就是转换类(第三方类),将原本返回的XML格式数据转换成json格式数据,而具体数据是怎么来的则直接用原有接口方法就可以。

  新客户只需要调用适配器类就可以了,而老客户这边也不会进行任何修改处理。

  如果再有新的客户要求其他类型的返回,只需要在适配器类中增加相应的转换处理就可以了。

  再思考一个问题,现实生活中空调插头一般都是三头的,但如果家里只有两孔插座,那必然是插不进去的。

  以前老的办法那就是把三头插座掰掉一个,另外两个也掰直,这样做存在很大的安全隐患,而且有时并不能工作。

  而如果提供一个拥有三孔插座和两头插头的转换器的话,那空调可以先插在这个转换器上,然后这个转换器再插在插座上就可以了。

  本质并没有变,只是将二孔插座包装了一下,向外界提供了一个三孔插座的外观以供客户使用。

  适配的本质就是转换,将不满足使用条件的东西通过第三方类进行加工处理成可使用的东西。

  适配器模式(Apapter Pattern)是一种结构型设计模式,将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口兼容而不能一起工作的那些类可以一起工作。  

  适配器模式用来解决现有对象与客户端期待接口不一致的问题。

  • 目标角色(Target):描述了其他类与客户端代码合作时必须遵循的协议。
  • 客户角色(Client):与符合Target接口的对象协同。
  • 被适配(服务类,功能类)(Adaptee):定义一个已经存在并已经使用的接口,这个接口需要适配。 客户端与其接口不兼容, 因此无法直接调用其功能。
  • 适配器(Adapter) :适配器模式的核心。适配器接受客户端通过适配器接口发起的调用,同时根据其内在逻辑调用对应服务类。客户端代码只需通过接口与适配器交互即可, 无需与具体的服务类耦合。

优缺点:

  • 单一职责原则:可以将接口或数据转换代码从主要业务逻辑中分离。
  • 开闭原则: 客户端接口只需适配器进行交互, 能在不修改现有代码的情况下在程序中添加新类型的适配器。
  • 通过适配器模式,可以使两个不兼容的接口协同工作,避免了修改现有代码的需要。
  • 提高了代码的复用性和灵活性,因为适配器可以重复使用,并且可以在不同的场景中使用。
  • 降低了系统的耦合度,适配器模式允许系统中的各个组件相互独立地演化。
  • 代码整体复杂度增加 :因为需要新增一系列接口和类。 有时直接更改服务类使其与其他代码兼容会更简单。

应用场景:

  系统需要复用现有类,但是接口又与复用环境要求不一致的情况。

  • 旧系统与新系统的兼容:可以使新系统能够无缝地与老旧系统进行通信
  • 第三方组件的集成:适配器可以将第三方组件的接口转换为符合我们系统需求的接口形式,从而能够顺利地集成到我们的系统中。
  • 多个类库之间的互操作:适配器模式可以起到桥梁的作用

创建方式:

  适配器模式有两种实现结构,对象适配器类适配器。

  试想一下,目前有一个三头插头的空调,需要一个三孔插座,但目前只有一个两孔插座。

  编写一个适配器来包装一下这个两孔插座,让用户可以使用这个空调。

  1. 类适配器

     1     /// <summary>
     2     /// 两孔插座---被适配者
     3     /// </summary>
     4     public class TwoHoleSocket
     5     {
     6         public void SpecificRequest()
     7         {
     8             Console.WriteLine("两孔插座");
     9         }
    10     }
    11 
    12     /// <summary>
    13     /// 三孔插座---目标角色
    14     /// </summary>
    15     public interface IThreeHoleSocket
    16     {
    17         void Request();
    18     }
    19 
    20     /// <summary>
    21     /// 适配器类提供了三孔插座的外观,但其本质是两孔插座
    22     /// </summary>
    23     public class PowerAdapter : TwoHoleSocket, IThreeHoleSocket
    24     {
    25         public void Request()
    26         {
    27             Console.WriteLine("提供三孔插座的外观");
    28             //执行两孔插座的功能
    29             this.SpecificRequest();
    30         }
    31     }
    32 
    33     /// <summary>
    34     /// 客户端
    35     /// </summary>
    36     class Client
    37     {
    38         static void Main(string[] args)
    39         {
    40             //客户端可以通过适配器来使用这个两孔插座了(因为外观已经是三孔的了)
    41             IThreeHoleSocket threeHoleSocket = new PowerAdapter();
    42             threeHoleSocket.Request();
    43             Console.ReadKey();
    44         }
    45     }
    View Code

    TwoHoleSocket类代表原有的两孔插座,IThreeHoleSocket接口来规范三孔插座的外观。

    PowerAdapter类代表适配器,将两孔插座赋予三孔插座的外观。

    这样用户就可以使用这个适配器来使用这个三头插头的空调了。

    从实例中可以看出,类适配器只要是用继承来实现的,但如果有很多个类进行适配,这个方式就不支持了。

  2. 对象适配器

     1     /// <summary>
     2     /// 两孔插座---被适配者
     3     /// </summary>
     4     public class TwoHoleSocket
     5     {
     6         public void SpecificRequest()
     7         {
     8             Console.WriteLine("两孔插座");
     9         }
    10     }
    11 
    12     /// <summary>
    13     /// 三孔插座---目标角色
    14     /// </summary>
    15     public class ThreeHoleSocket
    16     {
    17         // 客户端需要的方法
    18         public virtual void Request()
    19         {
    20             //具体实现
    21         }
    22     }
    23 
    24     /// <summary>
    25     /// 适配器类提供了三孔插座的外观,但其本质是两孔插座
    26     /// </summary>
    27     public class PowerAdapter : ThreeHoleSocket
    28     {
    29         //引用两孔插座的实例,从而将客户端与TwoHoleSocket联系起来
    30         public TwoHoleSocket twoHoleSocket = new TwoHoleSocket();
    31         public override void Request()
    32         {
    33             Console.WriteLine("提供三孔插座的外观");
    34             this.Request();
    35             //执行两孔插座的功能
    36             twoHoleSocket.SpecificRequest();
    37         }
    38     }
    39 
    40     /// <summary>
    41     /// 客户端
    42     /// </summary>
    43     class Client
    44     {
    45         static void Main(string[] args)
    46         {
    47             //客户端可以通过适配器来使用这个两孔插座了(因为外观已经是三孔的了)
    48             ThreeHoleSocket threeHoleSocket = new PowerAdapter();
    49             threeHoleSocket.Request();
    50             Console.ReadKey();
    51         }
    52     }
    View Code

    从实例中可以看出,对象适配器其实就是在适配器类中创建了一个被适配者的实例,从而将两者联系在一起。

    这种方式采用 “对象组合”的方式,更符合松耦合。

总结:

  总而言之,适配器就是一个第三方类,将不合时宜的东西转换成符合心意的工具类。

  本质就是转换。

  

标签:c#,适配器,三孔,接口,插座,两孔,public,详解
From: https://www.cnblogs.com/mingnianjiehunba/p/17729599.html

相关文章

  • C#基础 - Task
    目录前言1,Task的分类2,Task的状态2.1TaskStatus枚举2.2状态相关属性2.3小结3,Task的等待3.1Wait方法3.2死锁3.2.1死锁形成3.3.2死锁避免4,Task的结果4.1Result4.2GetAwaiter().GetResult()4.3await关键字5,Task的继续5.1ContinueWith方法5.2其他方法6,Task的启动6.1Start......
  • BeyondCompare 4 版本使用
    通过修改注册表的方法,使BeyondCompare版本4可以继续使用。修改注册表第一步:打开注册表。Win+R输入regedit,回车后即可打开注册表。 第二步:删除注册表中BeyondCompare软件中的注册参数CacheId。查找注册表路径:【HKEY_CURRENT_USER】--【S......
  • C面向对象
    类类是C语言结构体,包含两种不同的特性:数据(属性)和行为(操作)行为是对数据(属性)的操作最简单的实现类的方法是使用文件作为封装边界,公共变量和方法在头文件内可见,实现文件中包含方法体、私有变量和方法。对象对象是类的实例,创建类的实例,就是创建了结构体的实例(实际上就是创建了......
  • C# 中定义Task的扩展类
    目录一背景二代码分析1.ActionResult2Task的扩展类TaskExtension2.1Task中创建相互关联的Cancellation2.2Task中等待特定的结果返回2.3Task中等待执行结果的完成2.4Task执行增加Timeout2.5其它Task中使用的一些小技巧2.5完整的代码展示一背景在很多的时候我们代码中......
  • Mac M1 上体验 AI 作图保姆教程
    本文介绍如何在MacM1Pro上通过苹果CoreML来安装和运行StableDiffusion。HowtoInstallandRunStableDiffusiononYourM1MacbookProusingCoreML.苹果的开源工具包苹果开源了一个工具包CoreMLStableDiffusion,使用CoreML(苹果的机器学习模型)来实现AI作图,通过......
  • CPU占用率高怎么办?-华为
    一、查看CPU占用率displaycpu命令,查看CPU占用率。<HUAWEI>displaycpuCPUutilizationstatisticsat2017-12-0111:17:44945msSystemCPUUsingPercentage:12%CPUutilizationforfiveseconds:12%,oneminute:12%,fiveminutes:11%.MaxCPUUsage:......
  • 错误 [email protected]: Permission denied (publickey). fatal: Could not read from r
    场景:本地git已登录了账号,需要在github下载项目时提示[email protected]:Permissiondenied(publickey).fatal:Couldnotreadfromremoterepository.,解决方法是获取本地的密钥,在gitHub中添加即可,不需要有账号上的对应,不需考虑本地切换git账号问题. 1.判断错误情况:permissio......
  • service.getClass().getAnnotation(XXXAnnotation.class) 取值为Null
    springboot2.7java8问题在使用工厂模式封装service时,需要通过service的class获取其类型注解,但是有些工厂类可以取到annotation注解,有些取不到渠道注解:/***xxx渠道注解**/@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@int......
  • C++虚函数剖析-从二级指针角度
    tags:C++categories:C++写在前面一直说C++的多态,其实底层原理是虚函数支持,那么虚函数的底层原理呢,之前一直停留在表面,直到后来看了很多书籍/视频/博客文章,才有了一点深刻的理解,下面来具体看看如何通过C指针进行虚函数的调用,相当于对C指针的一个复习,同时也......
  • MacOS 使用 Asan 编译 C++报警告malloc: nano zone abandoned due to inability to re
    问题clang(llvm)编译c++程序,带内存问题检查工具选项-fsanitize=address-fsanitize=undefined之后出现:malloc:nanozoneabandonedduetoinabilitytoreservevmspace.解决vi~/.zshrc#加入:exportMallocNanoZone=0source~/.zshrc参考:ios-malloc:nanozonea......