适配器模式(Adapter Pattern):

  将某个类的接口转换成客户端期望的另一个接口表示,主要的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。如读卡器是作为内存卡和笔记本之间的适配器,需要将内存卡插入读卡器,再将读卡器插入笔记本,这样笔记本就可以读取内存卡了。

适配器模式的主要角色:

  设计模式-结构型-适配器模式_适配器模式

  1、目标接口(Target):当前系统业务所期待的接口,它可以是抽象类或接口。

  2、适配者类(Adaptee):被访问和适配的现存组件库中的组件接口。

  3、适配器类(Adapter):转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

适配器模式主要分三类:类适配器模式、对象适配器模式、接口适配器模式(java中使用)。接下来我们来详细介绍下这三种形式。

  1、类适配器模式

    当前去外地出差,工作繁忙,回到宾馆也不得不工作。当你拿出电脑,准备接电源,卧槽...不支持!!!电源是两孔的,而插座是三孔的,怎么办呢?你会想到去楼下小商店买个转换插座,将三孔插座转成两孔的来用,简直太聪明了。 

    设计模式-结构型-适配器模式_适配器模式_02(以该图代替,原理类似)

设计模式-结构型-适配器模式_适配器模式_03设计模式-结构型-适配器模式_设计模式_04

 1 internal class Program 2 { 3     private static void Main(string[] args) 4     { 5         Computer computer = new Computer(new TwoHoleSocket()); 6         computer.Connect(); 7         // 类适配器的缺点 8         TwoHoleSocket twoHoleSocket = new TwoHoleSocket(); 9         twoHoleSocket.Test();10     }11 }12 13 internal class Computer14 {15     private readonly Transformer transformer;16 17     public Computer(Transformer transformer)18     {19         this.transformer = transformer;20     }21 22     public void Connect()23     {24         transformer.Transfrom();25         Console.WriteLine("连接成功!!!");26     }27 }28 29 /// 30 /// 三孔插座Adaptee31 /// 32 internal class ThreeHoleSocket33 {34     public void Show()35     {36         Console.WriteLine("我是三孔插座");37     }38 39     public void Test()40     {41         Console.WriteLine("我是多余的");42     }43 }44 45 /// 46 /// 转换器Target47 /// 48 internal interface Transformer49 {50     void Transfrom();51 }52 53 /// 54 ///  两孔插座Adapter55 /// 56 internal class TwoHoleSocket : ThreeHoleSocket, Transformer57 {58     public void Transfrom()59     {60         base.Show();61         Console.WriteLine("转换中。。。。");62         Console.WriteLine("哈哈哈,我已经是两孔插座");63     }64 }

view code

    分析:对于类适配器来说,Adapter与Adaptee过于耦合,增加了使用成本,且会暴露不必要的方法。

  2、对象适配器模式

    当手机没电需要充电,你不可能直接使用220V的电压,如果你真这么做了,请注意人身安全及购买一台新机。此时,充电器就起到了转换器的作用,将220V电压转换成手机可使用的5V电压。

    设计模式-结构型-适配器模式_适配器模式_05

设计模式-结构型-适配器模式_适配器模式_03设计模式-结构型-适配器模式_设计模式_04

 1 class Program 2 { 3     static void Main(string[] args) 4     { 5         Phone phone = new Phone(); 6         phone.charging(new VoltageAdapter(new Voltage220V())); 7     } 8 } 9 10 class Phone11 {12     public void charging(Voltage5V voltage5V)13     {14         voltage5V.output5V();15     }16 }17 18 class Voltage220V19 {20     public void output220V()21     {22         Console.WriteLine("220V");23     }24 }25 26 interface Voltage5V27 {28     void output5V();29 }30 31 class VoltageAdapter : Voltage5V32 {33     private readonly Voltage220V voltage220V;34 35     public VoltageAdapter(Voltage220V voltage220V)36     {37         this.voltage220V = voltage220V;38     }39 40     public void output5V()41     {42         voltage220V.output220V();43         Console.WriteLine("5V");44     }45 }

view code

    分析:以松耦合的方式实现适配器模式,推荐使用。   

  3、接口适配器模式(java中使用,c#中能够实现但意义不大)

    设计模式-结构型-适配器模式_设计模式_08 

设计模式-结构型-适配器模式_适配器模式_03设计模式-结构型-适配器模式_设计模式_04

 1 class Program 2 { 3     static void Main(string[] agrs) 4     { 5         Power5VAdapter power5VAdapter = new Power5VAdapter(new AC220()); 6         Console.WriteLine(power5VAdapter.output5V()); 7     } 8 } 9 10 class AC22011 {12     public int output220V()13     {14         int output = 220;15         return output;16     }17 }18 19 interface Voltage20 {21     int output5V();22     int output9V();23     int output12V();24     int output24V();25 }26 27 abstract class PowerAdapter : Voltage28 {29     private readonly AC220 ac220;30 31     public PowerAdapter(AC220 ac220)32     {33         this.ac220 = ac220;34     }35 36     public virtual int output12V()37     {38         return ac220.output220V();39     }40 41     public virtual int output24V()42     {43         return ac220.output220V();44     }45 46     public virtual int output5V()47     {48         return ac220.output220V();49     }50 51     public virtual int output9V()52     {53         return ac220.output220V();54     }55 }56 57 class Power5VAdapter : PowerAdapter58 {59     private AC220 ac220;60 61     public Power5VAdapter(AC220 ac220)62         : base(ac220)63     {64         this.ac220 = ac220;65     }66 67     public override int output5V()68     {69         int output = 0;70         if (this.ac220 != null)71         {72             output = this.ac220.output220V() / 44;73         }74         return output;75     }76 }

view code

优点:

  1、客户端通过适配器可以透明地调用目标接口。

  2、复用了现存的类,开发人员不需要修改原有代码而重用现有的适配者类。

  3、将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。

缺点:

  1、对类适配器来说,更换适配器的实现过程比较复杂。

  2、过多的适配器,会让系统零乱,不易整体进行把握。