1、简介
通常,客户端通过类的接口访问它提供的服务,有时,现有的类可以提供客户类的功能需要,但是它所提供的接口不一定是客户类所期望的。在这种情况下,现有的接口需要转化为客户类期望的接口,这样保证了对现有类的重用,于是就需要用到适配器模式。适配器模式(Adapter)把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作,这种模式又称为转换器模式、变压器模式、包装(Wrapper)模式等。
模式所涉及的角色有:
目标(Target)角色:所期待得到的接口。
源(Adaptee)角色: 需要适配的接口。
适配器(Adapter)角色:适配器把源接口转换成目标接口,根据这一角色的实现不同,可分为
类适配器(Class Adapter)和
对象适配器(Object Adapter)。
类适配器是通过继承类适配者类(Adaptee Class)实现的,另外类适配器实现客户类所需要的接口。当客户对象调用适配器类方法的时候,适配器内部调用它所继承的适配者的方法。
对象适配器包含一个适配器者的引用(reference),与类适配器相同,对象适配器也实现了客户类需要的接口。当客户对象调用对象适配器的方法的时候,对象适配器调它所包含的适配器者实例的适当方法。
适配器模式的用意是将接口不同而功能相同或者相近的两个接口加以转换,包括适配器角色补充一些源角色没有但目标接口需要的方法。但不要误以为适配器模式就是为了补充源角色没有的方法而准备的。
类适配器(Class Adapter)
|
对象适配器(Object Adapter) |
基于继承概念 |
利用对象合成 |
可以重载适配者的方法 |
不太容易重载适配者的方法 |
如果需要改变多个已有的子类的接口,就要针对每一个子类做一个适配器类,而这不太实际。
如果源中有大量的方法,使用类的适配器模式则比较容易(不需要一一写出源类中的方法,而对象的适配器模式则要一一写出目标角色中的方法,如缺省适配器)
|
可以把多种不同的源适配到同一个目标,换言之,同一个适配器可以把源类和它的子类都适配到目标接口。
增加的新方法可以同时适用所有的源。
|
2、使用场景及能解决的问题
系统需要使用现有的类,而此类的接口不符合系统的需要。
想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有 很复杂的接口。
类或方法的作用相同但名称不同的类或方法之间进行适配。
3、类图
4、实例
首先看看我们需要达成的目标类:
package adapter;
public interface MyTarget {
public void request();
public void specRequest();
}
在看看已经有的适配者:
package adapter;
public class Adaptee {
public void specRequest() {
System.out.println("this is specRequest.");
}
}
接下来是我们的核心——适配器,包括类适配器和对象适配器两种实现方式:
package adapter;
public class ClassAdapter extends Adaptee implements MyTarget {
public void request() {
System.out.println("this is request");
}
}
package adapter;
public class ObjectAdapter implements MyTarget {
public void request(){
System.out.println("this is request");
}
public void specRequest(){
adaptee.specRequest();
}
private Adaptee adaptee = new Adaptee();
}
最后是调用的Client:
package adapter;
public class Client {
private static MyTarget ctarget = new ClassAdapter();
private static MyTarget otarget = new ObjectAdapter();
public static void main(String args[]){
ctarget.request();
ctarget.specRequest();
otarget.request();
otarget.specRequest();
}
}
5、缺省的适配器模式
缺省适配模式(Default Adapter Pattern)为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。
适配器模式的用意是要改变源的接口,以便与目标类的接口相容。缺省适配的用意稍有同,它是为了方便建立一个不平庸的适配器类而提供的一种平庸实现(就是为接口提供空的实现)。
在任何时候,如果不准备实现一个接口的所有方法时(一般在定义一个大的接口时都应该提供它的缺省适配类),就可以制造一个抽象类,给出所有方法的平庸的具体实现。这样,从这个抽象类再继承下去的子类就不必实现所有的方法了。缺省适配模式的中心是一个缺省适配类。这个类应当是抽象类。