定义:将一个类的接口转换成客户所期望的另一个接口,适配器让原本不兼容的接口可以配合工作。
对象适配器
由于java是单继承的,所以一般使用对象适配器比较多。
很经典的例子:笔记本电脑充电需要三相的插座,而现在只有二相的插座,那么就需要一个中间的转换器,一边插在二相的插座上,并在另外一边提供三相的插口。
这里面,笔记本电脑就属于Client,笔记本所期望的三相接口就是Target,即目标接口,原有的二相插座就是被适配者Adaptee,中间的转换器就是适配器Adapter。
需要进行的工作就是, 在笔记本充电的时候需要持有一个三相的插座接口(引用)进行充电,这个三相插座接口定义了使用三相插座进行充电的方法,我们要提前准备好一个实现了三相插座接口的适配器类,在其中实现三相接口充电的方法,而这个方法的内部实现其实是调用的二相插座的充电方法。
其实有点偷梁换柱的意思,表面上实现的是三相接口的充电方法,但其实内部是调用的二相接口的充电方法。
再抽象一点,客户端需要一个接口,这个接口中定义了一些客户端所需要的方法,我们创建一个类来实现这个接口中的方法,先不说我们这个类内部是怎么实现接口中的方法的,但是至少表面上,是满足了客户的需求的,因为客户所需要的就是一个目标接口的引用。
再来说这个类内部的具体实现,我们就可以调用现有的一些实现,即使原本是不符合客户的需求的,但是只要我们将这个方法写在了实现的接口方法的内部,就会被调用了,就可以在此基础上再增加一些额外的操作进一步满足客户的需求。
这样就完成了适配工作。
代码:
//target目标接口
public interface ThreePlug {
void useThreePlug();
}
//原有的需要被适配的类,即Adaptee
public class TwoPlug {
public void useTwoPlug(){
System.out.println("用二相电接口...");
}
}
//目标接口的实现类,即适配器
public class Adapter implements ThreePlug {
private TwoPlug adaptee;
public Adapter(TwoPlug adaptee){
this.adaptee = adaptee;
}
@Override
public void useThreePlug() {
System.out.println("三相转化为二相...");
adaptee.useTwoPlug();
}
}
//客户,需要一个目标接口的引用
public class NoteBook {
private ThreePlug threePlug;
public NoteBook(ThreePlug threePlug){
this.threePlug = threePlug;
}
public void charge(){
threePlug.useThreePlug();
}
}
public class Test {
public static void main(String[] args) {
TwoPlug twoPlug = new TwoPlug();
Adapter adapter = new Adapter(twoPlug);
NoteBook noteBook = new NoteBook(adapter);
noteBook.charge();
}
}
类适配器
其实对象适配器使用的是组合的方式,而类适配器使用的是继承的方式,在组合的方式中,适配器是持有的被适配者的一个引用,通过这个引用进行操作,而在继承的方式中则是适配器直接继承了被适配者,并实现了目标接口,这样的话就默认适配器已经具有了被适配者的功能,只需要进行额外的实现目标接口的方法即可。
代码:
public class Adapter2 extends TwoPlug implements ThreePlug {
@Override
public void useThreePlug() {
System.out.println("三相转化为二相...");
super.useTwoPlug();
}
public static void main(String[] args) {
Adapter2 adapter2 = new Adapter2();
NoteBook noteBook = new NoteBook(adapter2);
noteBook.charge();
}
}