疯狂餐厅
86.88M · 2026-03-21
你有没有遇到过这种情况?
如果你也深受其扰,那么今天我要介绍的设计模式——适配器模式,正是为你准备的。
说人话:它就是一个翻译官。
想象一下你去欧洲旅游插座不匹配,需要一个转换插头——适配器就是那个插头转换器。
在 Java 中,适配器模式主要有三种实现方式:
核心思路:适配器同时继承被适配者(Adaptee),并实现目标接口(Target)。
来看一个具体的例子。假设我们有两个充电标准:
// 目标接口 - 国标
public interface NationalStandard {
void use();
}
// 被适配者 - 英标(已有实现,不想改动)
public class EnglandStandard {
public void userDefault() {
System.out.println("当前是英标接口");
}
}
// 适配器
public class Adapter extends EnglandStandard implements NationalStandard {
@Override
public void use() {
// 调用英标的方法
userDefault();
// 做转换适配
System.out.println("→ 已转换为国标接口");
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
NationalStandard nationalStandard = new Adapter();
nationalStandard.use();
}
}
输出:
当前是英标接口
→ 已转换为国标接口
类适配器的特点:
核心思路:适配器不继承被适配者,而是持有它的实例。
// 同样的目标接口
public interface NationalStandard {
void use();
}
// 同样的英标实现
public class EnglandStandard {
public void userDefault() {
System.out.println("当前是英标接口");
}
}
// 对象适配器 - 持有而非继承
public class Adapter implements NationalStandard {
private EnglandStandard englandStandard = new EnglandStandard();
@Override
public void use() {
englandStandard.userDefault();
System.out.println("→ 对象适配器:已转换为国标接口");
}
}
输出:
当前是英标接口
→ 对象适配器:已转换为国标接口
对象适配器的特点:
核心思路:当一个接口方法太多,我们只需要实现其中几个时,可以用一个抽象适配器类空实现所有方法,子类按需覆盖。
// 有一个很多方法的接口
public interface AbsAdapterListener {
void start();
void pause();
void stop();
void end();
}
// 抽象适配器 - 空实现所有方法
abstract class AbstractAdapter implements AbsAdapterListener {
@Override
public void start() {}
@Override
public void pause() {}
@Override
public void stop() {}
@Override
public void end() {}
}
// 使用时只需覆盖关心的方法
public class Client {
public static void main(String[] args) {
// 只关心 start
new Player().listen(new AbstractAdapter() {
@Override
public void start() {
System.out.println("只回调 start 方法");
}
});
// 只关心 end
new Player().listen(new AbstractAdapter() {
@Override
public void end() {
System.out.println("只回调 end 方法");
}
});
}
}
适配器模式在日常开发中随处可见:
| 场景 | 说明 |
|---|---|
| 旧系统改造 | 老接口数据格式转新格式 |
| 第三方 SDK 接入 | 第三方库的接口转内部统一接口 |
| 不同支付渠道 | 支付宝、微信、银联各自一套接口,适配成统一支付接口 |
| 数据转换 | JSON 转 XML,Map 转 Object |
假设我们接入一个第三方天气 API:
// 内部统一天气接口(我们的目标)
public interface WeatherService {
WeatherResult getWeather(String city);
}
// 第三方SDK的旧接口(被适配者)
public class ThirdPartyWeatherSDK {
public Map<String, Object> query(String cityName) {
// 第三方返回的是 Map
Map<String, Object> result = new HashMap<>();
result.put("city", cityName);
result.put("temp", 22);
result.put("wd", "north");
return result;
}
}
// 适配器
public class WeatherAdapter implements WeatherService {
private ThirdPartySDK sdk = new ThirdPartySDK();
@Override
public WeatherResult getWeather(String city) {
// 调用旧接口
Map<String, Object> rawData = sdk.query(city);
// 转换为我们的格式
return WeatherResult.builder()
.city((String) rawData.get("city"))
.temperature((Integer) rawData.get("temp"))
.windDirection((String) rawData.get("wd"))
.build();
}
}
这样,调用方只需依赖 WeatherService 接口,完全不用关心背后对接的是哪个第三方。
| 适配器模式 | 装饰器模式 | |
|---|---|---|
| 目的 | 转换接口,实现兼容 | 增强功能 |
| 关系 | 通常是临时桥接 | 长期增强 |
| 新接口 | 改变原有接口 | 保持原有接口 |
| 举例 | 转换插头 | 给手机加壳 |
适配器模式的核心价值在于: