1.基本概念
- 将一个接口转化为客户希望的另一个接口,使接口不兼容的那些类可以一起工作,在适配器模式中,我们通过增加一个新的适配器解决接口不兼容的问题,使原本没有任何关系的类可以协同工作。
2.结构
适配器可以分为两种
-
对象适配器 从用户的角度看不到被适配者,用户调用适配器转换出来的接口方法。适配器再调用相关的接口方法,对于用户来说,用户感觉只是在和目标接口交互。适配器和适配者是关联关系
-
类适配器 适配器实现目标接口并且继承被适配者,适配器和适配者是继承关系。
3.角色
-
Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个接口或者抽象类,也可以是具体类
-
Adapter(适配器类):适配器可以调用另外一个接口,作为一个转换器,对被适配的角色和目标角色进行适配,在对象适配器中,
-
Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
4.案例
将大众伪装奔驰
- 对象适配器:
先定义一个奔驰接口,这是目标接口。
public interface BenCar {
void brand();//品牌名称方法
}
定义大众接口和大众的实现类,大众接口是被适配者。
public interface VolkCar {
void brand();//方法
}
public class VolkCarImpl implements VolkCar {
@Override
public void brand() {
System.out.println("这是奔驰");
}
}
构建适配器,通过有参构造初始化被适配者对象,在实现目标接口里面调用被适配者的方法,实现伪装,继承的是目标接口。实现的是被适配者的方法
//实现奔驰接口,但具体的方法调用的确实大众接口的。
public class CarAdapter implements BenCar {
private VolkCar volkCar;
public CarAdapter(VolkCar volkCar) {
this.volkCar = volkCar;
}
@Override
public void brand() {
volkCar.brand();
}
}
测试
public class CarTest {
public static void main(String[]args){
VolkCarImpl volkCar = new VolkCarImpl();
BenCar benCar= new CarAdapter(volkCar);
benCar.brand();
}
}
- 类适配器:
类适配器,是通过继承完成适配过程的,具体和对象适配器很像。我们只用更改下适配器的代码就可以了。
public class CarAdapter extends VolkCarImpl implements BenCar {
@Override
public void brand() {
super.brand();
}
}
这里适配器实现了目标接口,但在实现目标接口的方法里面调的是父类的方法,实现适配。
总而言之,适配器模式就是把不相关的接口联系起来,作为两个接口的桥梁。
5缺省适配器
缺省适配器主要解决的是我们能够选择的适配目标接口中的某个方法。并不想适配所有的方法又称为单接口适配器模式。
具体如下。
对于上面的奔驰目标接口,他可能还有一个发动机的方法,但是我们并不像对这个方法进行适配,但我们的适配器又实现这个目标接口,不能不实现这个发动机的方法。
public interface BenCar {
void brand();
void engine();//发动机
}
现在怎么办呢,可以创建一个抽象类,对目标接口的方法全部默认实现,如下
public abstract class CarAdapterAbstract implements BenCar {
@Override
public void brand() {
}
@Override
public void engine() {
}
}
更改我们的适配器,继承抽象类
public class CarAdapter extends CarAdapterAbstract {
private VolkCar volkCar;
public CarAdapter(VolkCar volkCar) {
this.volkCar = volkCar;
}
@Override
public void brand() {
volkCar.brand();
}
}
这样我们的适配器就可以选择方法适配了
java源码好多都用到适配器。比如 Reader、InputStream之间的适配,字符流、字节流之间的适配。大家没事可以研究研究。