适配器模式是把一个类的接口变成客户端所期待的另外一种接口,从而使本来因接口不匹配而没法在一块儿工做的两个类可以在一块儿工做。api
就像插头转换器,以前入了switch港版,插头是英式的,还好附赠一个插头转换器,适配器就至关于这个转换器。ide
分为类的适配器与对象的适配器两种this
把适配的类的api转化为目标类的apispa
上图中Adaptee没有2方法,可是客户端却指望调用2方法。为了客户端可以使用Adaptee类,提供中间类Adapter,把Adaptee与Target的api组合起来,Adapter与Adaptee是继承关系,因此这决定了适配器是类适配器。code
涉及到的角色:对象
目标(Target)角色:这就是所期待获得的接口。注意:因为这里讨论的是类适配器,所以目标不能是类。blog
源(Adapee)角色:如今须要适配的接口。继承
适配器(Adapter)角色:适配器类是本模式的核心。适配器把源接口转化成目标接口,显然这一角色不能够是接口必须是具体类。接口
类适配器代码:get
public interface Target { /** * 这是源类Adaptee也有的方法 */ public void sampleOperation1(); /** * 这是源类Adapteee没有的方法 */ public void sampleOperation2(); }
public class Adaptee { public void sampleOperation1(){} }
public class Adapter extends Adaptee implements Target { /** * 因为源类Adaptee没有方法sampleOperation2() * 所以适配器补充上这个方法 */ @Override public void sampleOperation2() { //写相关的代码 } }
适配器Adapter扩展了源类,也实现了目标接口,且提供了源类没有的接口的实现。
对象适配器模式
对象适配器与类适配器不一样的地方在于,对象适配器采用委派的方式将源类与适配器关联到一块儿(类适配器采用继承)
源代码:
public interface Target { /** * 这是源类Adaptee也有的方法 */ public void sampleOperation1(); /** * 这是源类Adapteee没有的方法 */ public void sampleOperation2(); }
public class Adaptee { public void sampleOperation1(){} }
public class Adapter { private Adaptee adaptee; public Adapter(Adaptee adaptee){ this.adaptee = adaptee; } /** * 源类Adaptee有方法sampleOperation1 * 所以适配器类直接委派便可 */ public void sampleOperation1(){ this.adaptee.sampleOperation1(); } /** * 源类Adaptee没有方法sampleOperation2 * 所以由适配器类须要补充此方法 */ public void sampleOperation2(){ //写相关的代码 } }
类适配器与对象适配器的权衡
综上,尽可能以对象适配器的实现方式为主,多用聚合,少用继承。固然具体问题具体分析,根据实际须要选择(我的认为实际上就不必对源类进行重写,若是须要进行重写直接对源类进行修改就好了,除非是没有代码权限,不过若是没有权限的话,那么源类对你来说更不可见,也就更没有重写的必要了吧。)。
更好的复用性:
系统须要使用现有的类,而此类的接口不符合系统的须要,那么经过适配器模式可让类得到更好的复用。
更好的扩展性:
在适配器实现功能的时候,也能够调用本身的功能,从而扩展系统的功能。
过多的适配器,会让系统显得更加凌乱,不容易把控。
重构的代价合适的话,确实要比适配器更合适。