发布时间

适配器模式(Adapter Pattern)

Authors
  • avatar
    Name
    lzs39
    Twitter

适配器模式(Adapter Pattern)

核心概念

适配器模式

定义:将一个类的接口转换成客户期望的另一个接口,使原本因接口不兼容而无法协同工作的类能够一起工作。其别名为 包装器(Wrapper)
详细:适配器模式属于[[结构型模式]],核心在于「解耦」与「桥接」——它不修改原有组件逻辑,而是通过中间层实现语义与调用契约的翻译。本质是面向对象中的「接口适配」问题在设计层面的标准化解决方案。
关联:[[目标抽象类]], [[适配者类]], [[适配器类]], [[开闭原则]], [[单一职责原则]], [[组合优于继承]]

类适配器 vs 对象适配器

  • 类适配器:采用继承 + 实现方式(extends Adaptee implements Target),适用于 Adaptee 为具体类且支持多继承语义(如 Java 中需借助接口+单继承限制下的模拟)。优点是结构紧凑;缺点是紧耦合、无法复用多个 Adaptee、违反[[组合优于继承]]原则。
  • 对象适配器:采用组合方式(Adapter has-a Adaptee),Adapter 持有 Adaptee 实例并委托调用。更符合现代设计原则,支持运行时动态替换 Adaptee,易于扩展和测试。
    关联:[[组合优于继承]], [[依赖倒置原则]], [[里氏替换原则]]

缺省适配器模式

定义:为接口提供一个默认实现的抽象类(空方法体),子类按需覆写部分方法。
详细:解决「接口爆炸」问题——当接口定义大量方法但客户端仅需少数时,避免强制实现无用方法。常用于事件监听(如 MouseAdapter, KeyAdapter)。
关联:[[接口隔离原则]], [[模板方法模式]]

双向适配器

定义:适配器同时持有 Target 和 Adaptee 的引用,支持双向调用(Target ↔ Adapter ↔ Adaptee)。
详细:适用于需要在两个方向上进行协议/数据格式互转的场景(如通信网关、跨平台 RPC 代理)。增加了灵活性,但也提高了复杂度与循环依赖风险。
关联:[[中介者模式]], [[桥接模式]]

关键要点

  1. 动机本质是「兼容性治理」:不是功能增强,而是消除集成障碍。典型场景包括遗留系统对接、第三方 SDK 集成、硬件驱动抽象、API 版本迁移等。
  2. 适配 ≠ 重构:适配器封装变化,而非消除变化;它承认差异存在,并提供稳定契约。真正的解耦应最终导向[[防腐层(Anti-Corruption Layer)]]建设。
  3. 目标抽象类(Target)决定契约权威性:Client 只依赖 Target,完全 unaware Adaptee 的存在——这是适配器模式实现「透明性」的关键。
  4. 适配器应保持「轻量翻译」职责:仅做接口转换与参数映射,避免掺杂业务逻辑。复杂转换建议引入[[策略模式]]或[[命令模式]]协同。
  5. 警惕「适配器链」陷阱:多层嵌套适配器(A→B→C→Target)会显著增加调试难度与性能损耗,需通过[[门面模式]]或统一协议层收敛。

方法论

类适配器实现步骤

  1. 定义目标接口 Target(客户期望的契约)
  2. 确认适配者类 Adaptee(已存在、不可修改的接口)
  3. 创建适配器类 Adapter继承 Adaptee 并实现 Target
  4. Adapter 中覆写 Target 方法,内部委托/转换调用 Adaptee 的对应方法
  5. Client 通过 Target 接口使用 Adapter 实例

适用场景:Adaptee 是具体类;语言支持多重继承语义(或 Java 中通过接口+单继承模拟);适配逻辑极简,无需运行时替换 Adaptee。

对象适配器实现步骤

  1. 定义目标接口/抽象类 Target
  2. 确认适配者类 Adaptee
  3. 创建适配器类 Adapter继承 Target(或实现 Target)并持有 Adaptee 引用
  4. 在构造器中注入或初始化 Adaptee 实例
  5. Adapter 方法中通过委托调用 Adaptee 行为
  6. Client 仍面向 Target 编程

适用场景:Adaptee 可能有多个变体;需支持运行时切换适配源;遵循组合优先原则;系统强调可测试性与松耦合。

个人洞察

  • 适配器模式常被误用为「万能胶水」,实则它是防御性设计:当无法控制一方接口时的妥协方案。理想状态是推动上游统一契约(如采用[[OpenAPI规范]]),而非无限堆砌适配层。
  • 现代框架中,适配器已下沉为基础设施能力:Spring 的 Converter/GenericConverter、MyBatis 的 TypeHandler、React 的 Adapter Component 均是其思想的工程化体现。
  • 在领域驱动设计(DDD)中,适配器是[[防腐层]]的核心实现机制——它隔离外部模型对核心域模型的污染,保障[[限界上下文]]边界清晰。
  • 注意区分「适配器」与「装饰器」:前者解决 接口不兼容,后者解决 功能增强;但二者都使用 Wrapper 别名,易混淆。关键判据:是否改变了对外契约(适配器改,装饰器不改)。

待探索问题

  • [ ] 如何结合[[策略模式]]构建可配置的适配器工厂,支持同一 Target 多种 Adaptee 动态切换?
  • [ ] 在微服务架构中,API 网关如何以适配器模式统一处理不同下游服务的协议(REST/gRPC/GraphQL)与认证方式?
  • [ ] 适配器模式与[[代理模式]]的边界在哪里?何时该用 Proxy(控制访问)而非 Adapter(转换接口)?
  • [ ] 前端开发中,如何用 TypeScript Interface + Adapter 函数实现跨 SDK(如微信/支付宝小程序 API)的统一调用层?

参考链接

  • 原文来源:https://blog.csdn.net/qq_44398094/article/details/111120845
  • GoF《设计模式》第 9 章:Adapter Pattern
  • Martin Fowler《Patterns of Enterprise Application Architecture》:Adapter & Anti-Corruption Layer
  • Spring Framework 官方文档:Converter SPI 机制
  • React 官方指南:Composition over Inheritance(组合优于继承原则实践)