前言
在之前的一篇博客中,我们详细探讨了Java代理模式------这种通过中间代理类控制目标对象访问、并对核心方法进行增强的设计模式,在Spring AOP、权限控制等场景中发挥着至关重要的作用。代理模式的核心是"不改变目标接口,只做功能增强",让我们在不侵入原有代码的前提下,灵活扩展业务逻辑。
而今天,我们要聊的是另一种同样常用的结构型设计模式------适配器模式,它与代理模式有着相似的"中间类"结构,却承载着完全不同的核心使命:如果说代理模式是"给原有功能加buff",那么适配器模式就是"让原本不相容的功能能并肩作战"。
接下来,我们就详细展开对适配器模式的讲解
一、什么是适配器模式?
1.定义
适配器模式(Adapter Pattern)是结构型设计模式 的一种,核心作用是让两个原本不兼容的接口 / 类能够协同工作,就像生活中的电源适配器:国内电器是两脚插头,国外插座是三孔插孔,通过电源适配器就能让两者匹配使用,无需修改电器或插座本身。

2.本质
在 Java 开发中,适配器模式的本质是:通过一个中间适配器类,将目标类的接口转换成客户端期望的接口,解决接口不兼容问题,同时遵循开闭原则(对扩展开放,对修改关闭)。
3.核心角色
适配器模式包含 4 个核心角色,缺一不可:
- 目标接口(Target) :客户端期望使用的接口,是业务的标准规范(比如「两脚充电接口」)。
- 适配者(Adaptee) :已存在的、功能可用但接口不兼容的类(比如「三孔电源插座」),是我们需要适配的对象。
- 适配器(Adapter) :核心中间类,实现 Target 接口,内部持有 Adaptee 对象,负责将 Target 的调用转换为 Adaptee 的调用。
- 客户端(Client):使用 Target 接口的业务方,只和目标接口交互,无需关心适配器和适配者。
4.设计思想
- 不修改原有代码:适配者和目标接口的源码都不改动,符合开闭原则,避免修改旧代码引发 bug。
- 解耦:客户端只依赖目标接口,和适配者完全解耦,扩展性极强。
- 复用:让已有的、功能完善的旧类能在新业务中继续使用,避免重复开发。
二、适配器模式的两种实现方式
Java 中适配器模式有两种经典实现:类适配器(继承实现) 和对象适配器(组合实现) ,开发中优先使用对象适配器(符合组合优于继承原则)。
1. 类适配器(继承实现)
(1)经典类适配器---功能合并
结构拆解:
- A 类(适配者 Adaptee) :已有类,提供了
m1()方法,但没有实现 B 接口。 - B 接口(目标接口 Target) :客户端期望的接口,定义了
m1()和m2()两个方法。 - 适配器 :继承 A 类 + 实现 B 接口 ,把 A 类的
m1()功能合并到 B 接口中,同时补充实现m2()方法,让客户端可以通过 B 接口调用 A 类的功能。
核心作用:
- 接口兼容转换:把已有类(A)的功能,适配成客户端期望的接口(B),让两者可以协同工作。
- 功能合并复用 :通过继承 A 类复用
m1(),通过实现 B 接口满足客户端的调用规范,同时补充m2()方法。 - 核心目标是解决接口不兼容问题,让原本无法一起工作的类和接口适配起来。

代码示例:
java
// 1. 适配者A类:已有功能,但接口不兼容
class A {
public void m1() {
System.out.println("A类的m1()方法:已有的功能");
}
}
// 2. 目标接口B:客户端期望的标准接口
interface B {
void m1();
void m2();
}
// 3. 类适配器:继承A类 + 实现B接口,完成适配
class Adapter extends A implements B {
// 继承A类,自动拥有了m1()方法,直接复用
@Override
public void m2() {
// 补充实现目标接口的m2()方法
System.out.println("适配器补充实现的m2()方法");
}
}
// 客户端:只依赖目标接口B
public class Client {
public static void main(String[] args) {
B target = new Adapter();
target.m1(); // 调用的是A类的m1()方法
target.m2(); // 调用的是适配器实现的m2()方法
}
}
(2)默认适配器---只想实现接口的指定类
结构拆解
- 目标接口 :定义了
m1()~m10()共 10 个方法,是一个多方法的通用接口。 - 适配器 :实现了这个接口,把
m1()~m10()所有方法都做了空实现 (比如public void m1() {})。 - 业务类 :继承适配器,只重写自己关心的
m1()方法,其他 9 个方法直接继承适配器的空实现,不用自己写。
核心作用
- 简化接口实现:避免了 "实现接口必须重写所有方法" 的冗余代码。
- 适配的是「接口和实现者」之间的关系,让实现者只关注自己需要的方法。

代码示例
java
// 1. 接口:方法很多,业务类只需要用其中一个
interface Target {
void m1();
void m2();
// ... 省略中间方法
void m10();
}
// 2. 适配器:实现接口,所有方法空实现
abstract class Adapter implements Target {
@Override public void m1() {}
@Override public void m2() {}
// ... 其他方法也都空实现
@Override public void m10() {}
}
// 3. 业务类:继承适配器,只重写需要的方法
class MyClass extends Adapter {
@Override
public void m1() {
// 只在这里写业务逻辑,其他方法不用管
System.out.println("我只关心m1()方法");
}
}
2.对象适配器(组合实现,推荐)
在类适配器里面的第一种经典类适配器:A类和B接口里面是有一个相同方法名的,但如果要合并的是方法名不同,但是实现的功能相同我们要怎么做?
那就可以使用对象适配器:
结构拆解:
- 适配者(Adaptee):
A类,含+m1()已有类,提供了可用的功能,但接口不兼容 - 目标接口(Target):
B接口,含+mm1()、+mm2()客户端期望的标准接口 - 适配器(Adapter): 中间的
适配器类核心中间层,实现目标接口 B,同时持有适配者 A 的对象
核心功能:
- 基于组合,而不是继承适配者:通过new对象来持有适配者对象
- 解决了Java单继承限制:类适配器受到Java单继承的限制,无法继承其他类,而对象适配器没有这个问题,可以同时持有多个适配器对象,适配多个不同的类

3.对比
| 维度 | 对象适配器 | 类适配器 |
|---|---|---|
| 实现方式 | 实现目标接口 + 持有适配者对象(组合) | 继承适配者 + 实现目标接口(继承) |
| Java 单继承限制 | 无限制,可同时适配多个类 | 受限制,只能继承一个适配者 |
| 耦合度 | 低,适配器与适配者松耦合 | 高,适配器与适配者强耦合 |
| 扩展性 | 强,可通过构造方法传入不同适配者 | 弱,适配者固定为继承的类 |
| 推荐程度 | ✅ 实际开发首选 | ❌ 仅在特殊场景使用 |
三、适配器模式 VS 代理模式
适配器模式和代理模式都属于结构型模式 ,且都有「中间类」,很多人容易混淆,这里讲一下核心区别:目的不同、作用不同、关注点不同。
1. 核心目的
-
适配器模式 :解决「接口不兼容」问题 ,让两个无法协同的类能一起工作,不新增功能,只做转换。
-
代理模式 :解决「对象访问控制」问题 ,不改变目标接口,对目标对象的方法进行增强 / 控制(如日志、事务、权限)。
2. 核心关系
-
适配器模式 :适配器 → 适配者(转换关系),目标接口和适配者接口不兼容。
-
代理模式 :代理类 → 目标对象(代理关系 ),代理类和目标对象实现同一个接口,接口完全一致。
3. 功能侧重点
-
适配器模式 :接口转换,不修改、不增强原有功能,只做兼容。
-
代理模式 :功能增强 / 访问控制,在目标方法执行前后添加额外逻辑,接口不变。
4. 代码层面区别
-
适配器:实现目标接口,内部调用适配者的不同方法(接口不兼容)。
-
代理:实现目标接口,内部调用目标对象的相同方法(接口一致)。