1、定义
定义一个包装类,用于包装不兼容的接口。分 类适配器模式、对象适配器模式
2、作用
把一个类接口变换成客户端所期待的另一种接口,从而使得原本接口不匹配而无法一起工作的两个类能够一起工作。
3、解决问题
原本不兼容而无法一起工作的那些类可以在一起工作。
4、模式原理
适配器将目标API跟源API衔接起来
4.1类的适配器模式
如上图,Target期待调用Request方法,但Adaptee并没有此方法。
Target:目标角色,期待得到接口,接口定义者。
Adapter:适配器角色,把源接口转换成目标接口。
Adaptee:源角色,源接口提供者。
类的适配器模式:继承Adaptee 和 实现Target接口
简单实例
步骤1: 创建Target接口;
public interface Target {
//这是源类Adapteee没有的方法
public void request();
}
步骤2: 创建源类(Adaptee)
public class Adaptee {
public void specificRequest(){
}
}
步骤3: 创建适配器类(Adapter)
//适配器Adapter继承自Adaptee,同时又实现了目标(Target)接口。
public class Adapter extends Adaptee implements Target {
//目标接口要求调用Request()这个方法名,但源类Adaptee没有方法Request()
//因此适配器补充上这个方法名
//但实际上Request()只是调用源类Adaptee的SpecificRequest()方法的内容
//所以适配器只是将SpecificRequest()方法作了一层封装,封装成Target可以调用的Request()而已
@Override
public void request() {
this.specificRequest();
}
}
步骤4:定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标
public class AdapterPattern {
public static void main(String[] args){
Target mAdapter = new Adapter();
mAdapter.request();
}
}
4.2对象适配器模式
与类适配器模式区别在于,Adaptee跟Adapter关系是委派方式。
简单例子
步骤1、2跟类适配器模式一样
步骤3: 创建适配器类(Adapter)(不适用继承而是委派)
class Adapter implements Target{
// 直接关联被适配类
private Adaptee adaptee;
// 可以通过构造函数传入具体需要适配的被适配类对象
public Adapter (Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// 这里是使用委托的方式完成特殊功能
this.adaptee.specificRequest();
}
}
步骤4:定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标
public class AdapterPattern {
public static void main(String[] args){
//需要先创建一个被适配类的对象作为参数
Target mAdapter = new Adapter(new Adaptee());
mAdapter.request();
}
}
5、此模式优缺点
5.1 优点
- 更好的复用性(可让系统现有的类更好的复用)
- 透明、简单(客户端可以调用同一接口,系统接口对于客户端是透明的)
- 更好扩展
- 解耦(目标类和源类解耦,无需修改原有代码)
- 符合开放-关闭原则
5.2 缺点
过多的使用适配器,会让系统非常零乱,不易整体进行把握
6、应用场景
- 系统需要复用现有的类。
- 多个组件功能类似,但接口不统一且可能经常切换。例如Retrofit、ListAdapter
7、总结
建议尽量使用对象的适配器模式,多用合成/聚合、少用继承。