适配器模式是Java中的结构性模式的一种,最近详细的比较安卓中的Listview和RecycleView的区别,有一点很明显,就是RecycleView中就根本没有添加header和footer的方法,像这种方法也是我们平时常用的,那么只能自己封装了,参考了Listview的做法发现里面用到了适配器的模式就静下心来好好研究了下适配器模式。
在阎宏博士的《JAVA与模式》一书中开头是这样描述适配器(Adapter)模式的:
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
我觉得这句话的总结的真的非常精辟,一语道破适配器模式的核心的思想。
我们先看适配器模式的例图:
我们来分析下这张图,其实平时的时候根本不需要适配,那我们的流程是什么样的呢?
此时用到的是Client Target ConcreteTarget,因为不需要适配所以Adaptee和Adapter是用不上的。
我们来看代码:
public class Client {
public static void main(String[] args) {
ConcreteTarget concreteTarget = new ConcreteTarget();
concreteTarget.request();
}
}
public interface Target {
void request();
}
public class ConcreteTarget implements Target{
@Override
public void request() {
System.out.println("我是正常的实现接口");
}
}
打印的结果:我是正常的实现接口那么问题来了,客户端知道Adaptee中有个onRequest()的功能,客户端想去玩玩这个功能,那怎么实现呢?你怎么办呢?这个时候就要用到适配器模式了。
适配器模式有2种,第一种是“面向类的适配器模式”,第二种是“面向对象的适配器模式”。
1 面向类的适配器模式
public class Adaptee {
public void onRequest() {
System.out.println("被适配类具有 特殊功能...");
}
}
public class Adapter extends Adaptee implements Target {
@Override
public void request() {
this.onRequest();
}
}
可以看出来,适配器继承了被适配者同时实现了目标接口,那么这个适配就能顺利成章的进行功能转换了。
再来看看客户端:
public class Client {
public static void main(String[] args) {
ConcreteTarget concreteTarget = new ConcreteTarget();
concreteTarget.request();
Adapter adapter = new Adapter();
adapter.request();
}
}
打印结果:我是正常的实现接口被适配类具有 特殊功能...
这样就实现了正常功能到特殊功能的转换,是不是很简单....
2 面向对象的适配器模式
public class Adapter2 implements Target {
Adaptee adaptee;
public Adapter2(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.onRequest();
}
}
对象适配器模式就是要求在适配器中传入被适配者的对象。
再看看测试的客户端:
public class Client {
public static void main(String[] args) {
ConcreteTarget concreteTarget = new ConcreteTarget();
concreteTarget.request();
//继承适配器模式
Adapter adapter = new Adapter();
adapter.request();
//对象适配器模式
Adapter2 adapter2 = new Adapter2(new Adaptee());
adapter2.request();
}
}
打印结果:我是正常的实现接口被适配类具有 特殊功能...
被适配类具有 特殊功能...
可以知道不管是继承的适配器模式还是对象的适配器模式都达到了我们想要的结果。
两种实现方式的比较:
类适配器使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式。
类适配器可以重定义Adaptee的部分行为,相当于子类覆盖父类的部分实现方法,而对象适配器不能。
建议尽量使用对象适配器的实现方式,多用合成/聚合、少用继承。当然,具体问题具体分析,根据需要来选用实现方式,最适合的才是最好的。