一. 介绍
即定义一个包装类,用于包装不兼容的对象
包装类 = adapter
被包装类 = adaptee
1.1 场景
- 系统需要复用现有类,而该类的接口不符合系统的需求
- 多个组件功能类似,但接口不统一且可能会经常切换
1.2 优点
- 更好的复用性
系统需要使用现有的类,而此类的接口不符合系统的需要 - 透明、简单
客户端可以调用同一接口,因而对客户端来说是透明的 - 更好的扩展性
在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能 - 解耦性
将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码 - 符合开放-关闭原则
同一个适配器可以把适配者类和它的子类都适配到目标接口;可以为不同的目标接口实现不同的适配器,而不需要修改待适配类
1.3 缺点
- 过多的使用适配器,会让系统非常零乱,不易整体进行把握
1.4 分类
- 类的适配器
- 对象的适配器
二. 类的适配器
使用继承关系,将被包装类的方法转换成目标方法
2.1 场景
- 需要重新定义Adaptee的部分行为
- 希望使用方便时
2.2 优点
- 使用方便,代码简化
仅仅引入一个对象,并不需要额外的字段来引用Adaptee实例
缺点
2.3 缺点
- 高耦合,灵活性低
使用对象继承的方式,是静态的定义方式
2.4 使用
1. 创建目标接口
public interface Target {
void requestFnc();
}
2. 创建被包装的类
public class Adaptee {
public void sourceFnc() {
System.out.println("adaptee fnc.");
}
}
3. 创建适配类
/**
* 类的适配器模式:使用继承关系连接到Adaptee类
*
* @author dkangel
*/
public class ClassAdapter extends Adaptee implements Target {
/**
* 适配目标方法
*/
@Override
public void requestFnc() {
super.sourceFnc();
System.out.println("convert sourceFnc to requestFnc.");
}
}
4. 使用
public class Main {
public static void main(String[] args) {
Target target = new ClassAdapter();
target.requestFnc();
}
}
三. 对象的适配器
与类的适配器一样,将被包装类的方法转换成目标方法
不同:类的适配器使用继承关系连接adaptee,对象的适配器使用委派关系连接adaptee
2.1 场景
- 灵活使用时
- 需要同时配源类和其子类
2.2 优点
- 灵活性高、低耦合
采用对象组合
的方式,是动态组合方式
2.3 缺点
- 使用复杂
需要引入对象实例
2.4 使用
1. 创建目标接口
public interface Target {
void requestFnc();
}
2. 创建被包装的类
public class Adaptee {
public void sourceFnc() {
System.out.println("adaptee fnc.");
}
}
3. 创建适配类
/**
* 对象的适配器模式:使用委派关系连接到Adaptee类
*
* @author dkangel
*/
public class ObjAdapter implements Target {
private Adaptee adaptee;
public ObjAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void requestFnc() {
this.adaptee.sourceFnc();
System.out.println("convert sourceFnc to requestFnc.");
}
}