设计模式-结构型-适配器模式
适配器模式(adapter pattern):
将某个类的接口转换成客户端期望的另一个接口表示,主要的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。如读卡器是作为内存卡和笔记本之间的适配器,需要将内存卡插入读卡器,再将读卡器插入笔记本,这样笔记本就可以读取内存卡了。
适配器模式的主要角色:
1、目标接口(target):当前系统业务所期待的接口,它可以是抽象类或接口。
2、适配者类(adaptee):被访问和适配的现存组件库中的组件接口。
3、适配器类(adapter):转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
适配器模式主要分三类:类适配器模式、对象适配器模式、接口适配器模式(java中使用)。接下来我们来详细介绍下这三种形式。
1、类适配器模式
当前去外地出差,工作繁忙,回到宾馆也不得不工作。当你拿出电脑,准备接电源,卧槽...不支持!!!电源是两孔的,而插座是三孔的,怎么办呢?你会想到去楼下小商店买个转换插座,将三孔插座转成两孔的来用,简直太聪明了。
(以该图代替,原理类似)
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 computer 14 { 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 /// <summary> 30 /// 三孔插座adaptee 31 /// </summary> 32 internal class threeholesocket 33 { 34 public void show() 35 { 36 console.writeline("我是三孔插座"); 37 } 38 39 public void test() 40 { 41 console.writeline("我是多余的"); 42 } 43 } 44 45 /// <summary> 46 /// 转换器target 47 /// </summary> 48 internal interface transformer 49 { 50 void transfrom(); 51 } 52 53 /// <summary> 54 /// 两孔插座adapter 55 /// </summary> 56 internal class twoholesocket : threeholesocket, transformer 57 { 58 public void transfrom() 59 { 60 base.show(); 61 console.writeline("转换中。。。。"); 62 console.writeline("哈哈哈,我已经是两孔插座"); 63 } 64 }
分析:对于类适配器来说,adapter与adaptee过于耦合,增加了使用成本,且会暴露不必要的方法。
2、对象适配器模式
当手机没电需要充电,你不可能直接使用220v的电压,如果你真这么做了,请注意人身安全及购买一台新机。此时,充电器就起到了转换器的作用,将220v电压转换成手机可使用的5v电压。
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 phone 11 { 12 public void charging(voltage5v voltage5v) 13 { 14 voltage5v.output5v(); 15 } 16 } 17 18 class voltage220v 19 { 20 public void output220v() 21 { 22 console.writeline("220v"); 23 } 24 } 25 26 interface voltage5v 27 { 28 void output5v(); 29 } 30 31 class voltageadapter : voltage5v 32 { 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 }
分析:以松耦合的方式实现适配器模式,推荐使用。
3、接口适配器模式(java中使用,c#中能够实现但意义不大)
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 ac220 11 { 12 public int output220v() 13 { 14 int output = 220; 15 return output; 16 } 17 } 18 19 interface voltage 20 { 21 int output5v(); 22 int output9v(); 23 int output12v(); 24 int output24v(); 25 } 26 27 abstract class poweradapter : voltage 28 { 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 : poweradapter 58 { 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 }
优点:
1、客户端通过适配器可以透明地调用目标接口。
2、复用了现存的类,开发人员不需要修改原有代码而重用现有的适配者类。
3、将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
缺点:
1、对类适配器来说,更换适配器的实现过程比较复杂。
2、过多的适配器,会让系统零乱,不易整体进行把握。