1.定义:
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
组成: 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
源角色(adaptee):需要适配的类或适配者类。
适配角色(adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
2.分类:
适配器模式有类的适配器模式和对象的适配器模式两种不同的形式。
(1)类的适配器模式比较通用的类图如图所示:
如图所示,适配器Adapter将被适配的对象的接口转换成客户端需要的Target所规定的接口。通过适配器,客户端可以将Adaptee类当作一个Target来与之协同工作。我们举个例子。我们首先定义目标Target接口,Target接口之规定了一个方法:request(),其代码如下所示:
package dp.adapter; public interface Target { public void request(); }
源对象Adaptee代码如下:
package dp.adapter; public class Adaptee { public void doSth() { System.out.println("做我自己的事情"); } }
对于适配器来说,要达到适配的作用,需要继承源对象Adaptee并且实现目标接口Target,我们看看代码:
package dp.adapter; public class Adapter extends Adaptee implements Target{ @Override public void request() { super.doSth(); } }
这样,客户端可以通过调用Target对象的request方法,享受到实际上Adaptee对象的doSth中提供的服务。这样一来,接口不匹配的问题就搞定了,代码如下:
package dp.adapter; public class Client { public static void main(String[] args) { Target t = new Adapter(); t.request(); } }
运行一下,结果如下:
(2)对象的适配器模式如图所示:
在这种适配器模式中,适配器类Adapter和源Adaptee之间的关系不再是集成关系,而是一种委托的关系。Adapter往往持有一个Adaptee的引用。我们将上面的代码例子中Adapter的代码进行修改:
package dp.adapter; public class Adapter2 implements Target{ private Adaptee adaptee; @Override public void request() { adaptee.doSth(); } }
我们运行Client端程序,结果没有什么变化。
3. 模式总结
1 优点
1.1 通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。
1.2 复用了现存的类,解决了现存类和复用环境要求不一致的问题。
1.3 将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
1.4 一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
2 缺点
对于对象适配器来说,更换适配器的实现过程比较复杂。
3 适用场景
关于什么时候使用适配器模式,大概有三种情况:
(1). 你想使用一个已经存在的类,而它的接口不符合你的需求,这个在处理旧系统时比较常见。
(2). 你想创建一个可以复用的类,该类可以和其他不相关的类或不可预见的累协同工作,这就是我们android开发者经常碰到的情况:我们常常自定义一个新的Adapter。
(3). 你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配他的父类接口。