在介绍适配器原则之前介绍一下Abstract Server模式。
上面的图示描述的是一个开关类(Switch)控制灯具(Light)的开关。但是现在的这个关系违反了依赖翻转,Switch的功用被固定在了Light上面。如果以后有需求控制车门或者其他,那么就需要修改Switch,这样违反了开闭原则(OCP)。为了对修改/扩展开放,使用Abstract Server 模式:
通过一个接口,将Switch和Light隔离,已从实现了对修改的开放(所谓的开放是指如果增加或者改变Light种类,不会对Switch和Light有改动,也就是“只有增加,没有修改”)。
这是一种比较理想的情况,就是Light这个类本身是在我们的控制之下,但是如果Light是一个第三方控件,或者是一个已经编译好dll,我们无法对其进行修改,那么就需要使用Adapter模式对其进行“代理”。
Adapter就是这样为接口和实现类之间进行转接调用。
首先使用一个接口,让Switch和Light进行隔离,实现OCP,然后再使用一个Adapter来实现接口和实现类关联,这就是Adapter的寓意。Adapter有些和Proxy类似,都是用一个接口和实现类隔离开,在Bob大叔的书中也是将两者放在了前后两章节中。
1)我们发现Proxy模式中实现类和代理类都是我们可控的,他们可以都是继承自同一个接口,所以可控性有差别。
2)使用目标上面,Proxy目标是分离职能(在Order的例子中实现访问DB和订单业务的分离),以及为真实的对象做代理(比如对于大的图片的处理可以使用Proxy来作为图片的索引,只有真正使用的时候再加载,实现“延迟加载”,其实可以理解为真实对象的一个处理类),限制其访问。而作为Adapter则主要是当真是对象无法和接口匹配,比如无法继承,比如实现类和接口的逻辑设计有冲突,这时候就需要Adapter来适配一下,让接口和实现类能够通信(Switch实际访问的是Adapter,通过访问Adapter来访问Light)。
Adapter/Abstract Server(AA)和Proxy(P)还有一个功用的使用场景就是隔离。如果访问的是第三方控件或者某个不稳定的类库(后期可能换),这个时候可以考虑使用AA或者P,这样做的好处是把所有的变更的可能都集中在一个地方,如果修改只是修改Adapter而已,如果对于修改不能开放,那么就把他集中,也是Adapter/Abstract Server的隐喻之一。
Layer是依赖于Application,这种方式实现了DIP。