基础介绍:

  想象这样一个场景,原项目中接口返回的数据是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 }

    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 }

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

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

总结:

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

  本质就是转换。

  

c#中适配器模式详解的更多相关文章

  1. winxp计算机管理中服务详解

    winxp计算机管理中服务详解01 http://blog.sina.com.cn/s/blog_60f923b50100efy9.html http://blog.sina.com.cn/s/blo ...

  2. cocos2dx常见的46中+22中动作详解

    cocos2dx常见的46中+22中动作详解 分类: iOS2013-10-16 00:44 1429人阅读 评论(0) 收藏 举报 bool HelloWorld::init(){    ///// ...

  3. Android中Context详解 ---- 你所不知道的Context

    转自:http://blog.csdn.net/qinjuning/article/details/7310620Android中Context详解 ---- 你所不知道的Context 大家好,  ...

  4. iOS中-Qutarz2D详解及使用

    在iOS中Qutarz2D 详解及使用 (一)初识 介绍 Quartz 2D是二维绘图引擎. 能完成的工作有: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成 ...

  5. 【转】declare-styleable的使用(自定义控件) 以及declare-styleable中format详解

    原文网址:http://www.cnblogs.com/622698abc/p/3348692.html declare-styleable是给自定义控件添加自定义属性用的 1.首先,先写attrs. ...

  6. Python中dict详解

    from:http://www.cnblogs.com/yangyongzhi/archive/2012/09/17/2688326.html Python中dict详解 python3.0以上,pr ...

  7. 【转】 java中HashMap详解

    原文网址:http://blog.csdn.net/caihaijiang/article/details/6280251 java中HashMap详解 HashMap 和 HashSet 是 Jav ...

  8. java中HashMap详解(转)

    java中HashMap详解 博客分类: JavaSE Java算法JDK编程生活       HashMap 和 HashSet 是 Java Collection Framework 的两个重要成 ...

  9. java集合(2)- java中HashMap详解

    java中HashMap详解 基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 H ...

  10. PHP中Trait详解及其应用

    w PHP中Trait详解及其应用 - 开发者日常 - SegmentFaulthttps://segmentfault.com/a/1190000008009455

随机推荐

  1. 利用java来实现计算器的加减乘除

    package bag; import java.util.Scanner; public class Demo06 { public static void main(String[] args) ...

  2. 【阅读笔记】Rapid, Detail-Preserving Image Downscaling

    Rapid, Detail-Preserving Image Downscaling(快速的图像缩放技术) 该论文提出了一种基于卷积滤波器的算法,并确定滤波器的权值,使重要的细节保留在缩小比例的图像. ...

  3. Map集合_HashMap_TreeMap_等_小记

    Map是一种依照键值对数据存储元素的容器. Map中的元素是两个对象,一个对象作为键,一个对象作为值.一个键(key)和它对应的值构成map集合中的一个元素.Map集合的数据结构只跟键有关,键不可以重 ...

  4. Python数据分析易错知识点归纳(五):横向对比

    五.横向对比 排序 # 列表 a.sort() # 修改原列表,返回值为None!!!!!这里很容易出错 sorted(a) # 生成新的列表 # 嵌套列表的排序(若是对字典排序,需先用list()转 ...

  5. 基于LLVM的海量数据排序算法研究。(二维表的排序算法)

    当待排序数据内容大于内存容量时,需将待排序内容分块,要进行排序的分块传入内存,未处于排序状态的存入外存,外存的读写时间是内存的百万倍,因此在内外存储器之间传输分块所消耗的 I/O 时间是大数据排序算法 ...

  6. linux下卸载vnc

    sudo apt-get purge realvnc-vnc-server推荐连接:https://askubuntu.com/questions/653321/how-to-uninstall-re ...

  7. .NET下数据库的负载均衡“经典方案”(大项目必备,建议收藏)

    [前言] 本文讲述的"数据库负载均衡"方案,为市面上最经典(没有之一),由.NET界骨灰级大佬推出.采用该技术方案的大公司,一年省下了几个亿的支出. [正文] 支持.Net Cor ...

  8. MySQL5.5+配置主从同步并结合ThinkPHP5设置分布式数据库

    前言: 本文章是在同处局域网内的两台windows电脑,且MySQL是5.5以上版本下进行的一主多从同步配置,并且使用的是集成环境工具PHPStudy为例.最后就是ThinkPHP5的分布式的连接,读 ...

  9. 论文解读(APCA)《Adaptive prototype and consistency alignment for semi-supervised domain adaptation》

    [ Wechat:Y466551 | 付费咨询,非诚勿扰 ] 论文信息 论文标题:Adaptive prototype and consistency alignment for semi-super ...

  10. 拖拽宫格vue-grid-layout详细应用及案例

    目录 1.前言 2.安装 3.属性 4.事件 5.占位符样式修改 6.案例 1.前言 vue-grid-layout是一个适用于vue的拖拽栅格布局库,功能齐全,适用于拖拽+高度/宽度自由调节的布局需 ...