记录书上设计模式学习过程中的知识点,以便日后查看。
推荐《Android源码 设计模式》,挺不错的一本书。
一、适配器模式的定义:
适配器模式把一个类的接口变换成客户所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
二、适配器模式的使用场景
1、系统需要使用现有的类,而此类的接口不符合系统的要求,即接口不兼容。
2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些能在将来引进的类一起工作。
3、需要一个统一的输出接口,而输入端的类型不可预知。
三、适配器模式的UML图
1、类适配器模式
类适配器是通过实现Target接口以及继承Adaptee类来实现接口转换,例如,目标接口需要的是operation2,但是Adapter对象只有一个operation3,因此就出现了接口不兼容的情况。此时通过Adapter实现一个operation2函数将Adapter的operation3转换为Target需要的operation2,以此实现兼容。
角色介绍:
Target :目标角色,也就是所期待的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。
Adaptee:现在需要适配的接口。
Adapter:适配器角色,也是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。
简单示例:
笔记本电源适配器:220V(adaptee) 经过适配器(adapter)变成 5V (target)
//Target 角色
public interface FiveVolt {
public int getVolt5();
}
//Adaptee 角色,需要被转换的对象
public class Volt220 {
public int getVolt220() {
return 220;
}
}
//Adapter 角色,将220V的电压转换成5V的电压
public class VoltAdapter extends Volt220 implements FiveVolt {
@Override
public int getVolt5() {
Return 5;
}
}
public class Test {
public static void main(String[] args) {
VoltAdapter adapter = new VoltAdapter();
System.out.println(“输出电压:” + adapter.getVolt5());
}
}
Target角色给出了需要的目标接口,而Adaptee类则是需要被转换的对象。Adapter则是将220转换成Target.
2、对象适配器模式
Adaptee类(Voltage220)并没有getVolt5()方法,而客户端则期待这个方法。为使客户端能够使用Adapter类,需要提供一个包装类Adapter。这个包装类包装了一个Adaptee的实例,从而包装类能够把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。
示例代码:
//Target 角色
Public interface FiveVolt {
Public int getVolt5();
}
//Adaptee 角色,需要被转换的对象
Public class Volt220 {
Public int getVolt220() {
Return 220;
}
}
//对象适配器模式
public class VoltAdapter implements FiveVolt {
Volt220 mVolt220;
public VoltAdapter(Volt220 adaptee) {
mVolt220 = adaptee;
}
public int getVolt220() {
return mVolt220.getVolt220();
}
@Override
public int getVolt5() {
return 5;
}
}
public class Test {
public static void main(String args[]) {
VoltAdapter adapter = new VoltAdapter(new Volt220());
System.out.println(“输出电压:” + adapter.getVolt5());
}
}
这种实现方式直接将要被适配的对象传递到Adapter中,使用组合的形式实现兼容的效果。这比类适配器方式更加灵活,它的另一个好处是被适配器对象中的方法不会暴露出来,而类适配器由于继承了被适配对象,因此,被适配对象中的函数在Adapter类中也都有,这使得Adapter类出现一些比较奇怪的接口,用户使用成本较高。因此,对象适配器模式更加灵活、实用。
在实际开发中,Adapter通常应用于进行不兼容的类型转换的场景,还有一种就是输入有无数种情况,但是输出类型是统一的,我们可以通过Adapter返回一个统一的输出,而具体的输入留给用户处理,内部只需知道输出是符合要求的类型即可。例如ListView的Adapter,用户的ItemView各式各样,但最终都是View类型,ListView只需要知道getView返回的是一个View即可,具体是什么View类型并不需要ListView关心。而在使用Adapter模式的过程中建议尽量使用对象适配器的实现方式,多用合成或者聚合,少用继承。当然,具体问题具体分析,根据需要来选用实现方式,最适合的才是最好的。