vczh的日常 2018-04-08
使用适配器模式的一个重要的点是首先要识别出什么代码(接口)是已经存在的,什么代码(接口)是新的,需要去适配的。适配器的作用是让旧的(现有的)接口能够匹配新的系统(要去适配的)。
比如有下面两个接口,一个是系统已经有的:
public interface IDuck
{
void Quack();
void Fly();
}
鸭子接口是系统已经有的,我们现在要开发一套针对火鸡的,火鸡的接口是这样的:
public interface ITurkey { void Gobble(); void Fly(); }
我们要用这个火鸡去做一些事情,如果直接用的话火鸡和现有的鸭子接口是不匹配的,我们不能在需要一个鸭子的地方放进去一个实例化的火鸡。系统会报错。。。
那么我们现在要做的就是这样:
public class DuckAdapter:IDuck { private ITurkey _turkey; public DuckAdapter(ITurkey turkey) { _turkey = turkey; } public void Quack() { _turkey.Gobble(); } public void Fly() { _turkey.Fly(); } }
我们要给鸭子做一个适配器,这个适配器根据控制反转的原则,不依赖具体实现,依赖的是抽象的ITurkey(作为这个类的私有成员),然后在运行时动态的传入(DI)一个ITurkey的实例。
DuckAdapter实现了IDuck的接口,这样就实现了和原有系统的类型一致性,然后再利用对象组合的的方式(这个满足多用组合,少用继承的面向对象设计原则)对火鸡的成员进行调用。
下面用一个接插头来比喻这件事情:
上图中,ITurkey就是一个客户,而IDuck是一个被适配者,对于整个系统而言,IDuck是旧系统,是已经存在的系统,我们要将ITurkey适配到已有系统上面,直接搞是不行的,需要有一个中间的“适配器”来做适配。这个适配器就是上述代码中的DuckAdapter类。
如果不用适配器,就得改写客户端的代码来对新的接口(ITurkey接口)进行合适的调用。将会花费大量的精力来对调查和改写代码。相比之下,提供一个适配器,将所有的改变封装在一个类中,是比较好的做法。
适配器的工作是将一个接口转换成另一个,但是我们的世界实在是太复杂了,有的时候需要使用一个新的适配器来包装多个被适配者。
还有一种是双向适配器,可以用实现多个接口的方式来达成这个目标,这里的多个接口指得是新的接口和旧的接口都实现。
下面给出适配器模式的定义:将一个类的接口,转换成客户期望的另一个接口,适配器让原本接口不相容的类型合作无间。
与适配器模式类似的是外观模式,请看下一章。
前几篇介绍了设计模式的特性并且详细讲解了4种创建型模式,创建型模式是负责如何产生对象实例的,接下来讲讲结构型模式。结构型模式是解析类和对象的内部结构和外部组合,通过优化程序结构解决模块之间的耦合问题。