适配器模式将一个类的程序设计接口转换成另一个接口。这就很像变压器把一种电压换成另一种电压。例如,美国的生活用电电压是110V,而中国的电压是220V。如果要在中国使用美国电器,就必须有一个能把220V电压转换成110V电压的变压器,这个变压器就是Adapter。
1、意图
复用已存在的接口与所需的接口不一致的类
- 对象适配器:将原始类包含在新类里,然后在新类里创建方法区转换调用(通过关联来实现)。
- 类适配器:从一个不一致的类派生出一个类,然后在派生类里面增加所需要的方法,使得派生类能够匹配所需要的接口(通过继承来实现)。
从图中可以看出,Adaptee类没有Request方法,而客户期待这个方法。为了使客户能够使用Adaptee类,需要提供一个中间环节,即Adapter类,Adapter类实现了Target接口,并继承自Adaptee,Adapter类的Request方法重新封装了Adaptee的SpecificRequest方法,实现了适配的目的。因为Adapter与Adaptee是继承关系,所以这决定了这个适配器模式是类的
2、两种适配器模式
类适配器模式:
- 目标(Target)角色:是客户所期待的接口。因为java不支持多继承,所以Target必须是接口,不可以是类
- 源(Adaptee)角色:需要适配的类
- 适配器(Adapter)角色:把源接口转换成目标接口,这一角色必须是类
对象的适配器模式结构图
客户端需要调用Request方法,而Adaptee类没有该方法,为了使客户端能够使用Adaptee类,需要提供一个包装的类Adapter。这个包装类包装了一个Adaptee的实例,从而将客户端与Adaptee衔接起来。因为Adapter与Adaptee是委派关系,所以决定了这个适配器模式是对象的
对象适配器模式:
- 目标(Target)角色:是客户所期待的接口。Target可以是接口,也可以是抽象或具体的类
- 源(Adaptee)角色:需要适配的类
- 适配器(Adapter)角色:通过在内部包装(Wrap)一个Adaptee对象,把源接口转换成目标接口
实例:我们国家的民用电都是 220V,美国是 110V,而我们的手机充电一般需要 5V,这时候要充电,就需要一个电压适配器,将 220V 或者 110V 的输入电压变换为 5V 输出
类适配器:
package com.ag.structure;
public class AdapterMode {
public static void main(String[] args) {
Adapter adapter = new Adapter();
System.out.println(adapter.outPut5v());
}
}
interface Target{
int outPut5v();
}
interface Voltage {
int outputAC();
}
class AC110 implements Voltage {
public final int output = 110;
public int outputAC() {
return output;
}
}
class AC220 implements Voltage {
public final int output = 220;
public int outputAC() {
return output;
}
}
class Adapter extends AC110 implements Target{
public int outPut5v() {
int i = outputAC();
System.out.println("110V-->5V");
return 5;
}
}
class Adapter2 extends AC220 implements Target{
public int outPut5v() {
int i = outputAC();
System.out.println("220V-->5V");
return 5;
}
}
类适配器对于每一个Adaptee的子类都需要做一个适配器,会使得适配器越来越多
对象适配器:
package com.ag.structure;
public class AdapterMode {
public static void main(String[] args) {
Adapter adapter = new Adapter(new AC110());
System.out.println(adapter.outPut5v());
}
}
interface Target{
int outPut5v();
}
interface Voltage {
int outputAC();
}
class AC110 implements Voltage {
public final int output = 110;
public int outputAC() {
return output;
}
}
class AC220 implements Voltage {
public final int output = 220;
public int outputAC() {
return output;
}
}
class Adapter implements Target{
private Voltage voltage;
public Adapter(Voltage voltage){
this.voltage = voltage;
}
public int outPut5v() {
int i = voltage.outputAC();
System.out.println("110V-->5V");
return 5;
}
}
3、适用范围
- 系统需要使用现有的类,而此类的接口不符合系统的需要
- 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口
- 对象适配器在设计时需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这个不太实际