还在用 if-else 做兼容?三分钟学会适配器模式,让你的代码更优雅

前言

你有没有遇到过这种情况?

同事接手了一个老项目,发现旧接口返回的数据格式和新系统完全不兼容。于是他在代码里写满了 if-else,企图在每个调用的地方做转换。结果不仅代码臃肿不堪,一处修改就牵连一堆地方报错。

如果你也深受其扰,那么今天我要介绍的设计模式------适配器模式,正是为你准备的。

什么是适配器模式?

适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示,主要目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。

说人话:它就是一个翻译官

想象一下你去欧洲旅游插座不匹配,需要一个转换插头------适配器就是那个插头转换器。

适配器的三种形态

在 Java 中,适配器模式主要有三种实现方式:

1. 类适配器 ------ 继承实现

核心思路:适配器同时继承被适配者(Adaptee),并实现目标接口(Target)。

来看一个具体的例子。假设我们有两个充电标准:

  • 国标(Target):我们期望使用的接口
  • 英标(Adaptee):已有的旧实现
csharp 复制代码
// 目标接口 - 国标
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();
    }
}

输出

复制代码
当前是英标接口
→ 已转换为国标接口

类适配器的特点

  • 优点:直接继承,调用简单
  • 缺点:Java 单继承,灵活性受限

2. 对象适配器 ------ 组合实现(推荐)

核心思路 :适配器不继承被适配者,而是持有它的实例。

csharp 复制代码
// 同样的目标接口
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("→ 对象适配器:已转换为国标接口");
    }
}

输出

复制代码
当前是英标接口
→ 对象适配器:已转换为国标接口

对象适配器的特点

  • ✅ 更灵活,不受单继承限制
  • ✅ 推荐优先使用
  • ⚠️ 代码稍多一步

3. 接口适配器 ------ 解决接口臃肿

核心思路:当一个接口方法太多,我们只需要实现其中几个时,可以用一个抽象适配器类空实现所有方法,子类按需覆盖。

less 复制代码
// 有一个很多方法的接口
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:

typescript 复制代码
// 内部统一天气接口(我们的目标)
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 接口,完全不用关心背后对接的是哪个第三方。


适配器模式 vs 装饰器模式

适配器模式 装饰器模式
目的 转换接口,实现兼容 增强功能
关系 通常是临时桥接 长期增强
新接口 改变原有接口 保持原有接口
举例 转换插头 给手机加壳

简单记忆:适配器是"穿马甲"(换皮),装饰器是"穿衣服"(加功能)


总结

适配器模式的核心价值在于:

  1. 解耦 ------ 客户端依赖抽象,不关心具体实现
  2. 复用 ------ 旧代码不用重写,稍作适配就能上场
  3. 规范 ------ 统一接口,方便扩展
相关推荐
佩奇大王1 小时前
P2118 排列字母
java·开发语言·算法
zhoupenghui1681 小时前
golang中常用的设计模式举例
设计模式
东离与糖宝1 小时前
告别 Python!Java 本地部署 Qwen 3.5 实战,Ollama + Spring Boot 保姆级教程
java·人工智能
runfarther2 小时前
Java变量作用域详解
java·开发语言
java1234_小锋2 小时前
Java高频面试题:MyBatis与JPA有哪些不同?
java·开发语言·mybatis·jpa
gameboy0312 小时前
【异常解决】Unable to start embedded Tomcat Nacos 启动报错
java·tomcat
gameboy0312 小时前
Windows操作系统部署Tomcat详细讲解
java·windows·tomcat
fengxin_rou2 小时前
黑马点评实战篇|第五篇:分布式锁-redission
java·数据库·redis·后端·缓存
tsyjjOvO2 小时前
Spring 核心知识点全解析(续)
java·后端·spring