设计模式---适配器模式(转自可都可可博客)

1、引言


   从今天开始咱们开始讲【结构型】设计模式,【结构型】设计模式有以下几种:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。【建立型】的设计模式解决的是对象建立的问题,那【结构型】设计模式解决的是类和对象的组合关系的问题。今天咱们就开始讲【结构型】设计模式里面的第一个设计模式,中文名称:适配器模式,英文名称:Adapter Pattern。提及这个模式其实很简单,在现实生活中也有不少实例,好比:咱们手机的充电器,充电器的接头,有的是把两相电转换为三相电的,固然也有把三相电转换成两相电的。咱们常用笔记本电脑,笔记本电脑的工做电压和咱们家里照明电压是不一致的,固然也就须要充电器把照明电压转换成笔记本的工做电压,只有这样笔记本电脑才能够正常工做。太多了,就不一一列举了。咱们只要记住一点,适配就是转换,把不能在一块儿工做的两样东西经过转换,让他们能够在一块儿工做。

2、适配器模式的详细介绍

2.一、动机(Motivate)

   在软件系统中,因为应用环境的变化,经常须要将“一些现存的对象”放在新的环境中应用,可是新环境要求的接口是这些现存对象所不知足的。如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能知足新的应用环境所要求的接口?

2.二、意图(Intent)

   将一个类的接口转换成客户但愿的另外一个接口。Adapter模式使得本来因为接口不兼容而不能一块儿工做的那些类能够一块儿工做。                                                                   --《设计模式》Gof

2.三、结构图(Structure)

   适配器有两种结构

  1】、-对象适配器(更经常使用

        

     对象适配器使用的是对象组合的方案,它的Adapter核Adaptee的关系是组合关系。

     OO中优先使用组合模式,组合模式不适用再考虑继承。由于组合模式更加松耦合,而继承是紧耦合的,父类的任何改动都要致使子类的改动。

  2】、-类适配器
       
        

2.四、模式的组成

      能够看出,在适配器模式的结构图有如下角色:

      (1)、目标角色(Target):定义Client使用的与特定领域相关的接口。
   
      (2)、客户角色(Client):与符合Target接口的对象协同。
 
      (3)、被适配角色(Adaptee):定义一个已经存在并已经使用的接口,这个接口须要适配。
 
      (4)、适配器角色(Adapte) :适配器模式的核心。它将对被适配Adaptee角色已有的接口转换为目标角色Target匹配的接口。对Adaptee的接口与Target接口进行适配.

2.5 适配器模式的具体实现

   因为适配器模式有两种实现结构,今天咱们针对每种都实现了本身的方式。

   一、对象的是适配器模式实现
javascript

复制代码
 1 namespace 对象的适配器模式
 2 {
 3     ///<summary>
 4     ///家里只有两个孔的插座,也懒得买插线板了,还要花钱,可是个人手机是一个有3个小柱子的插头,明显直接搞不定,那就适配吧
 5     ///</summary>
 6     class Client
 7     {
 8         static void Main(string[] args)
 9         {
10             //好了,如今就能够给手机充电了
11             TwoHoleTarget homeTwoHole = new ThreeToTwoAdapter();
12             homeTwoHole.Request();
13             Console.ReadLine();
14         }
15     }
16 
17     /// <summary>
18     /// 我家只有2个孔的插座,也就是适配器模式中的目标(Target)角色,这里能够写成抽象类或者接口
19     /// </summary>
20     public class TwoHoleTarget
21     {
22         // 客户端须要的方法
23         public virtual void Request()
24         {
25             Console.WriteLine("两孔的充电器可使用");
26         }
27     }
28 
29     /// <summary>
30     /// 手机充电器是有3个柱子的插头,源角色——须要适配的类(Adaptee)
31     /// </summary>
32     public class ThreeHoleAdaptee
33     {
34         public void SpecificRequest()
35         {
36             Console.WriteLine("我是3个孔的插头也可使用了");
37         }
38     }
39 
40     /// <summary>
41     /// 适配器类,TwoHole这个对象写成接口或者抽象类更好,面向接口编程嘛
42     /// </summary>
43     public class ThreeToTwoAdapter : TwoHoleTarget
44     {
45         // 引用两个孔插头的实例,从而将客户端与TwoHole联系起来
46         private ThreeHoleAdaptee threeHoleAdaptee = new ThreeHoleAdaptee();
47         //这里能够继续增长适配的对象。。
48 
49         /// <summary>
50         /// 实现2个孔插头接口方法
51         /// </summary>
52         public override void Request()
53         {
54             //能够作具体的转换工做
55             threeHoleAdaptee.SpecificRequest();
56             //能够作具体的转换工做
57         }
58     }
59 }
复制代码


   二、类的适配器模式实现
java

复制代码
 1 namespace 设计模式之适配器模式
 2 {
 3     /// <summary>
 4     /// 这里手机充电器为例,咱们的家的插座是两相电的,可是手机的插座接头是三相电的
 5     /// </summary>
 6     class Client
 7     {
 8         static void Main(string[] args)
 9         {
10             //好了,如今能够充电了
11             ITwoHoleTarget change = new ThreeToTwoAdapter();
12             change.Request();
13             Console.ReadLine();
14         }
15     }
16  
17     /// <summary>
18     /// 我家只有2个孔的插座,也就是适配器模式中的目标角色(Target),这里只能是接口,也是类适配器的限制
19     /// </summary>
20     public interface ITwoHoleTarget
21     {
22         void Request();
23     }
24  
25     /// <summary>
26     /// 3个孔的插头,源角色——须要适配的类(Adaptee)
27     /// </summary>
28     public abstract class ThreeHoleAdaptee
29     {
30         public void SpecificRequest()
31         {
32             Console.WriteLine("我是三个孔的插头");
33         }
34     }
35  
36     /// <summary>
37     /// 适配器类,接口要放在类的后面,在此没法适配更多的对象,这是类适配器的不足
38     /// </summary>
39     public class ThreeToTwoAdapter:ThreeHoleAdaptee,ITwoHoleTarget
40     {
41         /// <summary>
42         /// 实现2个孔插头接口方法
43         /// </summary>
44         public void Request()
45         {
46             // 调用3个孔插头方法
47             this.SpecificRequest();
48         }
49     }
50 }
复制代码

   代码都很简答,谁均可以看得懂,也有详细的备注

3、适配器模式的实现要点:
    
      一、Adapter模式主要应用于“但愿复用一些现存的类,可是接口又与复用环境要求不一致的状况”,在遗留代码复用、类库迁移等方面很是有用。

  二、GoF23定义了两种Adapter模式的实现结构:对象适配器和类适配器。类适配器采用“多继承”的实现方式,在C#语言中,若是被适配角色是类,Target的实现只能是接口,由于C#语言只支持接口的多继承的特性。在C#语言中类适配器也很难支持适配多个对象的状况,同时也会带来了不良的高耦合和违反类的职责单一的原则,因此通常不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神,对适配的对象也没限制,能够一个,也能够多个,可是,使得重定义Adaptee的行为较困难,这就须要生成Adaptee的子类而且使得Adapter引用这个子类而不是引用Adaptee自己。Adapter模式能够实现的很是灵活,没必要拘泥于GoF23中定义的两种结构。例如,彻底能够将Adapter模式中的“现存对象”做为新的接口方法参数,来达到适配的目的。

  三、Adapter模式自己要求咱们尽量地使用“面向接口的编程”风格,这样才能在后期很方便地适配。

      适配器模式用来解决现有对象与客户端期待接口不一致的问题,下面详细总结下适配器两种形式的优缺点。

     1】、类的适配器模式:

         优势:

               (1)、能够在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”

               (2)、能够从新定义Adaptee(被适配的类)的部分行为,由于在类适配器模式中,Adapter是Adaptee的子类

               (3)、仅仅引入一个对象,并不须要额外的字段来引用Adaptee实例(这个便是优势也是缺点)。

         缺点:

               (1)、用一个具体的Adapter类对Adaptee和Target进行匹配,当若是想要匹配一个类以及全部它的子类时,类的适配器模式就不能胜任了。由于类的适配器模式中没有引入Adaptee的实例,光调用this.SpecificRequest方法并不能去调用它对应子类的SpecificRequest方法。

               (2)、采用了 “多继承”的实现方式,带来了不良的高耦合。

        2】、对象的适配器模式

             优势:

                  (1)、能够在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”(这点是两种实现方式都具备的)

                  (2)、采用 “对象组合”的方式,更符合松耦合。

            缺点:

                  (1)、使得重定义Adaptee的行为较困难,这就须要生成Adaptee的子类而且使得Adapter引用这个子类而不是引用Adaptee自己。

     3】、适配器模式使用的场景:

              (1)、系统须要复用现有类,而该类的接口不符合系统的需求

              (2)、想要创建一个可重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在未来引进的类一块儿工做。

              (3)、对于对象适配器模式,在设计里须要改变多个已有子类的接口,若是使用类的适配器模式,就要针对每个子类作一个适配器,而这不太实际。

4、.NET 中适配器模式的实现

    说道适配器模式在Net中的实现就不少了,好比:System.IO里面的不少类都有适配器的影子,当咱们操做文件的时候,其实里面调用了COM的接口实现。如下两点也是适配器使用的案例:

      1.在.NET中复用COM对象:

    COM对象不符合.NET对象的接口,使用tlbimp.exe来建立一个Runtime Callable Wrapper(RCW)以使其符合.NET对象的接口,COM Interop就好像是COM和.NET之间的一座桥梁。

  2..NET数据访问类(Adapter变体):

   各类数据库并无提供DataSet接口,使用DbDataAdapter能够将任何个数据库访问/存取适配到一个DataSet对象上,DbDataAdapter在数据库和DataSet之间作了很好的适配。固然还有SqlDataAdapter类型了,针对微软SqlServer类型的数据库在和DataSet之间进行适配。

数据库

相关文章
相关标签/搜索