适配器模式
- 基本介绍
- 将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式
- 在适配器模式中,我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。
- 根据适配器类与适配者类的关系不同,适配器模式可分为对象适配器和类适配器两种,在对象适配器模式中,适配器与适配者之间是关联关系;在类适配器模式中,适配器与适配者之间是继承(或实现)关系。
类适配器
角色:
- Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类
- Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
- Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
下面我们以日常的充电器来说明,大家知道,我们日常家庭电压是220V(适配者),但是我们的手机充电不是用220V充电的,而是需要一个充电器把220V转成自己需要的电压(目标抽象类)
代码说明:
适配者类(被适配类)
public class Voltage220V {
public int outPut220V() {
int v = 220;
System.out.println("v = " + v);
return v;
}
}
目标抽象接口
public interface IVoltage5V {
public int outPut5V();
}
适配器类
public class VoltageAdapter extends Voltage220V implements IVoltage5V {
@Override
public int outPut5V() {
// 我们要输出5V电压,必须要用到父类的进行220V进行适配,转成适合自己的电压
int outPut220V = super.outPut220V();
int outPut5V = outPut220V/44;
return outPut5V;
}
}
测试:
public class MyTest {
public static void main(String[] args) {
IVoltage5V voltageAdapter = new VoltageAdapter();
int i = voltageAdapter.outPut5V();
System.out.println("i = " + i);
}
}
总结:
- java是单继承机制,所以类适配器模式需要继承适配者类算是一个缺点,因为这就需要目标抽象类必须是接口,有一定的局限性
- 适配者类的方法会在适配器类暴露出来,也增加使用成本,
对象适配器
- 基本介绍
- 对象适配器和类适配器墨水笔相同,只是将
Adapter
类作了修改,不是继承适配者类
,而是持有适配者类
的实例,以解决兼容性问题。- 根据合成复用原则,在系统中尽量使用关联关系来代替继承关系。
- 对象适配器模式是适配器模式常用的一种
我们来把上面的类适配器模式改成对象适配器模式:
适配者类(被适配类)
public class Voltage220V {
public int outPut220V() {
int v = 220;
System.out.println("v = " + v);
return v;
}
}
目标抽象接口
public interface IVoltage5V {
public int outPut5V();
}
适配器类(不在是继承,而是持有适配者类的对象)
public class VoltageAdapter extends Voltage220V implements IVoltage5V {
private Voltage220V voltage220V;
public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int outPut5V() {
int outPut220V =voltage220V.outPut220V();
int outPut5V = outPut220V/44;
return outPut5V;
}
}
总结:
- 对象适配器和类适配器算是同一种思想,只不过实现方式不同。根据合成复用原则,使用组合代替继承,所以他解决了类适配器模式必须继承被适配类的局限性问题,也不需要目标类必须是接口了。
- 对象适配器模式使用成本更低,更加灵活。
- 适配器模式主要用于几种情况:(1)系统需要使用现有的类,但现有的类不完全符合需要。(2)讲彼此没有太大关联的类引进来一起完成某项工作(指对象适配)。
接口适配器模式(默认适配器模式)
这种模式的核心归结如下:当你想实现一个接口但又不想实现所有接口方法,只想去实现一部分方法时,就用默认的适配器模式,他的方法是在接口和具体实现类中添加一个抽象类,而用抽象类去空实现目标接口的所有方法。而具体的实现类只需要覆盖其需要完成的方法即可
代码如下:
接口(定义了许多方法)
public interface Interface {
public void m1();
public void m2();
public void m3();
public void m4();
}
抽象类(对接口的方法进行默认实现)
public abstract class AbsAdapter implements Interface {
//默认实现
public void m1() {
}
public void m2() {
}
public void m3() {
}
public void m4() {
}
}
具体实现类(只需要覆盖其需要完成的方法)
public class Client {
public static void main(String[] args) {
AbsAdapter absAdapter = new AbsAdapter() {
//只需要去覆盖我们 需要使用 接口方法
@Override
public void m1() {
// TODO Auto-generated method stub
System.out.println("使用了m1的方法");
}
};
absAdapter.m1();
}
}
适配器模式源码分析
适配器模式在SpringMVC框架的源码分析:
- SpringMVC中的HandlerAdapter就使用了适配器模式。