适配器模式

适配器模式

一、什么是适配器模式?

适配器模式(Adapter Design Pattern):将一个类的接口转换成希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

适配者模式的几个特点:

  • 已存在旧接口实现
  • 希望使用新接口,但是又不想重新实现,想要复用已有的旧接口实现类

适配器模式,就是将旧接口实现适配为新接口。

二、适配器模式用来做什么?

2.1 模式原理

  • 将现有的业务功能旧接口重新封装,改用新接口调用

  • 统一多个实现类的接口设计,为外部提供统一的接口调用

  • 替换外部依赖的接口,改成自己系统的接口

  • 本质上,就是在不改变旧接口实现的情况下,将旧接口转为为新接口

  • 比如说,系统一开始没有设计接口规范,先实现的业务功能,后来才想起要定接口规范,但同时希望能够保留原有的实现代码

2.2 实际场景

Java 中有很多日志框架,在项目开发中,我们常常用它们来打印日志信息。

其中,比较常用的有 log4j、logback,以及 JDK 提供的 JUL(java.util.logging) 和 Apache 的 JCL(Jakarta Commons Logging) 等。

大部分日志框架都提供了相似的功能,比如按照不同级别(debug、info、warn、erro……)打印日志等,但它们却并没有实现统一的接口。

这时候,Slf4j 就出现了,提供了统一的接口定义,但它是在 JUL、JCL、log4j 等日志框架出现后才设计的。

然而,日志框架也不可能牺牲掉版本兼容性,将原本的接口改造成符合 Slf4j 接口规范。

所以 Slf4j 不仅仅提供了统一的接口定义,还提供了针对不同日志框架的适配器。

最后,在开发时,统一使用 Slf4j 提供的接口来打印日志,具体使用哪种日志框架实现(log4j、logback……),可以动态地指定。

三、适配器模式的结构是怎么样的?

适配器模式可以分为2种:

  • 类适配器:适配以类继承的形式实现
  • 对象适配器:适配以类组合的形式实现

这2种实现方式的区别:

  • 类适配器采用继承来实现,同时拥有旧接口和新接口的功能
  • 对象适配器采用组合实现,只实现了新接口
  • 类适配器的代码耦合度较高

适配器结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 新接口
public interface ITarget {
}

// 旧接口实现类
public class Adaptee {
}

// 类适配器: 基于继承
public class Adapter extends Adaptee implements ITarget {
}

// 对象适配器:基于组合
public class Adapter implements ITarget {
private Adaptee adaptee;
}

四、怎么实现一个适配器?

4.1 类适配器

  • 可采用多重继承方式实现
  • C++ 可定义一个适配器类,来同时继承当前系统的业务接口和现有组件库中已经存在的组件接口
  • Java 不支持多继承,但可以定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件
1
2
3
// 类适配器: 基于继承
public class Adapter extends Adaptee implements ITarget {
}

4.2 对象适配器

  • 采用组合的方式
  • 适配类实现新接口,同时将旧接口实现类注入适配类中
1
2
3
4
// 对象适配器:基于组合
public class Adapter implements ITarget {
private Adaptee adaptee;
}

五、适配器有什么优缺点?

优点:

  • 复用了现有的类,不需要修改原有代码
  • 通过适配类来解耦,新接口和原有接口耦合性较低

缺点:

  • 类结构变得复杂
  • 代码可读性降低

六、模式扩展

适配器模式,可扩展为双向适配器模式。

既可以把适配者(Adaptee)转换为新接口(Target),也可以把新接口(Target)转换为适配者接口(Adaptee)。

作者

jiaduo

发布于

2022-01-15

更新于

2023-04-03

许可协议