1.定义
Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn't otherwise becasue of incompatible interfaces(将一个类的接口变换成客户端所期待的另一个接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。)
适配类模式又叫做变压器模式,也叫做包装模式,但是包装模式可不止一个,还包括了装饰模式。
2.模式说明
为了更好的理解适配器模式的使用场景,下面使用一个示例进行说明。A,B两个图框代表已经制造成型的物体A和物体B,那现在要求把A和B安装在一起使用,如何安装?两者的接口不一致,是不可能直接安装在一起使用的,那要怎样解决这个问题呢?引入一个物体C,如下图所示:
引入物体C后,C适应了物体A的接口,同时也适应了B的接口,然后三者就可以组合成一个完整的物体了。其中的物体C就是我们所要讲的适配器,它在中间起到了角色转换的作用。
适配器模式有两种形式,一种是类适配器,另一种是对象适配器,下面分别介绍。
3.类适配器
(1)类图
Target目标角色:该角色定义把其他类转换为何种接口,也就是我们所期望的接口。
Adeptee源角色:你想把谁转换成目标角色,这个"谁"就是源角色,它是已经存在的、运行良好的类或对象,经过适配器角色的包装,它会转变成一个新的角色。
Adapter适配器角色:适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:把源角色转换为目标角色,通过什么进行转换呢?通过继承(类适配器)或类关联(对象适配器)的方式。
(2)通用源码
1 namespace ConsoleApplication1 2 { 3 /// <summary> 4 /// 目标角色 5 /// </summary> 6 public interface ITarget 7 { 8 void Write(); 9 } 10 11 /// <summary> 12 /// 目标角色的实现类 13 /// </summary> 14 public class ConcreteTarget : ITarget 15 { 16 public void Write() 17 { 18 Console.WriteLine("这是原有的逻辑"); 19 } 20 } 21 22 /// <summary> 23 /// 源角色 24 /// </summary> 25 public class Adaptee 26 { 27 public void WriteLog() 28 { 29 //具体的业务逻辑 30 Console.WriteLine("这是新的逻辑"); 31 } 32 } 33 34 /// <summary> 35 /// 适配器角色 36 /// </summary> 37 public class Adapter : Adaptee, ITarget 38 { 39 public void Write() 40 { 41 WriteLog(); 42 } 43 } 44 45 class Program 46 { 47 static void Main(string[] args) 48 { 49 //原有的业务逻辑 50 ITarget target = new ConcreteTarget(); 51 52 target.Write(); 53 54 //增加了适配器后的业务业务逻辑 55 ITarget newTarget = new Adapter(); 56 57 newTarget.Write(); 58 59 Console.ReadKey(); 60 } 61 } 62 }
在类适配方式中,我们得到的适配器类Adapter具有它所继承的父类的所有的行为,同时也具有接口ILogTarget的所有行为,这样其实是违背了面向对象设计原则中的类的单一职责原则。而且假如具有多个adaptee的话,我们同时需要创建多个adapter进行适配。
4.对象适配类
(1)类图
(2)通用源码
1 namespace ConsoleApplication1 2 { 3 /// <summary> 4 /// 目标角色 5 /// </summary> 6 public interface ITarget 7 { 8 void Write(); 9 } 10 11 /// <summary> 12 /// 目标角色的实现类 13 /// </summary> 14 public class ConcreteTarget : ITarget 15 { 16 public void Write() 17 { 18 Console.WriteLine("这是原有的逻辑"); 19 } 20 } 21 22 /// <summary> 23 /// 源角色接口 24 /// </summary> 25 public interface IAdaptee 26 { 27 void WriteLog(); 28 } 29 30 /// <summary> 31 /// 源角色 32 /// </summary> 33 public class Adaptee : IAdaptee 34 { 35 public void WriteLog() 36 { 37 //具体的业务逻辑 38 Console.WriteLine("这是新的逻辑"); 39 } 40 } 41 42 /// <summary> 43 /// 适配器角色 44 /// </summary> 45 public class Adapter : ITarget 46 { 47 private readonly IAdaptee _adaptee; 48 49 public Adapter(IAdaptee adaptee) 50 { 51 _adaptee = adaptee; 52 } 53 54 public void Write() 55 { 56 _adaptee.WriteLog(); 57 } 58 } 59 60 class Program 61 { 62 static void Main(string[] args) 63 { 64 //原有的业务逻辑 65 ITarget target = new ConcreteTarget(); 66 67 target.Write(); 68 69 //增加了适配器后的业务业务逻辑 70 ITarget newTarget = new Adapter(new Adaptee()); 71 72 newTarget.Write(); 73 74 Console.ReadKey(); 75 } 76 } 77 }
5.适配器模式的应用
(1)实现要点
.Adapter模式主要应用于"希望复用一些现存的类,但是接口又与复用环境要求不一致的情况",在遗留代码复用、类库迁移等方面非常有用。
.Adapter模式有对象适配器和类适配器两种形式的实现结构,但是类适配器采用"继承"的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用"对象组合"的方式,更符合松耦合精神。
.Adapter模式本身要求我们尽可能地使用"面向接口的编程"方式,这样才能在后期很方便的适配。
(3)注意事项
适配器模式最好在详细设计阶段不要考虑它,它不是为了解决还处在开发阶段的问题,而是解决正在服役的项目问题而存在的。
参考
1.设计模式之禅