适配器模式
定义
将一个类的接口转换成客户想要的接口,它使得原本两个不能同时使用的类可以一起使用。
结构
Target:客户端所期待的接口,它可以是具体类、抽象类或者接口。
Adatpter:适配器类,它将不同接口的类作为成员变量,接口中调用方法,实现接口互通。
Adaptee:与客户端所期待接口不一致的类。
类图
Adapter:
public class Adapter extends Target{
SpecificAdaptee adaptee = new SpecificAdaptee();
public void request() {
adaptee.specificRequest();
}
}
Adaptee:
public class SpecificAdaptee{
public void specificRequest(){
System.out.println("特殊请求");
}
}
Target:
public class Target{
public void request(){
System.out.println("普通请求");
}
}
测试类:
public static void main(String[] args) {
Target target = new Target();
target.request();
Target target1 = new Adapter();
target1.request();
}
结果:
案例
下面以110v电器和220v电器举例,我们要让110v的电可以通过适配器给110v的电器充电。
220v电器类:
public class CNelectricEquipment {
protected void charging220v() {
System.out.println("中国电器充电");
}
}
110v电器类:
public class USElectricEquipment {
protected void charging110v() {
System.out.println("美国电器充电");
}
}
适配器类:
public class PowerAdapter extends CNelectricEquipment{
USElectricEquipment electricEquipment = new USElectricEquipment();
protected void charging220v() {
System.out.println("将110v电转换为220v电");
electricEquipment.charging110v();
}
}
测试类:
public static void main(String[] args) {
CNelectricEquipment cNelectricEquipment = new CNelectricEquipment();
cNelectricEquipment.charging220v();
CNelectricEquipment cNelectricEquipment1 = new PowerAdapter();
cNelectricEquipment1.charging220v();
}
结果:
优点
1.可以使2个不同方法的类调用同一个接口。 2.提供类复用。
缺点
适配器模式是在已经开发完的项目中为了和别的项目对接使用的,而不是在项目设计阶段使用的,所以使用过多的适配器模式会造成系统变复杂,维护难度加大。
JDK类库中的适配器模式
java.util.Arrays#asList()
javax.swing.JTable(TableModel)
java.io.InputStreamReader(InputStream)
java.io.OutputStreamWriter(OutputStream)
javax.xml.bind.annotation.adapters.XmlAdapter#marshal()
javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal()
Arrays.asList(数组)内部实现其实调用了ArrayList的有参构造器,它们的功能都是传入一个数组并返回一个list集合。
@SafeVarargs
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
Jtable(java.swing包下基本不用)是JComponent的子类,JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) 构造器通过super()调用了父类的构造方法,它们的目的都是实例化一个对象。
OutputStreamWriter、InputStreamReader的有参构造器都调用了父类的super()方法,像这类调用父类super方法的都可以看成是适配器模式的提现。
XmlAdapter是一个java bean和xml互转的接口,实现XmlAdapter接口就可以实现marshal方法和unmarshal方法,这2个方法的主要功能是将特殊类型转换成需要的样式。