首页/开发/代码质量与评审速查/适配器模式 Adapter(结构型)
设计原则与模式62 条

适配器模式 Adapter(结构型)

把不兼容接口转成调用方期望的接口:包装第三方 SDK、遗留模块、异构协议;适配器只做转换与错误映射,不含业务规则,保持薄与可测。

适配器模式是什么

把不兼容的接口转成调用方期望的接口,让两套既有代码在不改对方的前提下协作。典型对象是第三方 SDK、遗留模块、异构协议。形态上对象适配(组合)优先于类适配(多重继承),因为组合不占继承位、也更容易替换实现与在测试里换桩。适配器只做转换与错误映射,它是防腐层最常见的具体做法:外部模型的变动被挡在边界之外。

基本信息

意图接口转换、屏蔽不兼容
形态对象适配(组合,优先)/ 类适配(多重继承)
边界只做翻译与错误映射,不含业务规则
位置系统边界、依赖方向向内的收口处
命名按被适配对象命名(SmsAdapter),而不是按模式命名

典型使用场景

  • 包装第三方短信、支付、地图 API,隔离它们的参数风格与错误码
  • 让遗留系统的旧接口符合新代码的领域接口
  • 同一能力接多家供应商时,为每家写一个适配器,上层只认统一接口
  • 把不同格式(JSON、XML、CSV)的输入统一成内部模型
  • 测试环境用内存实现替换真实客户端,接口不变
  • 新旧接口并行期让两套签名同时可用,逐步迁移调用方

Java 示例

Java 示例
public interface Notifier { void send(String to, String text); }

class SmsAdapter implements Notifier {
    private final ThirdPartySms sms;   // 组合,不继承
    SmsAdapter(ThirdPartySms sms) { this.sms = sms; }

    @Override
    public void send(String to, String text) {
        try {
            sms.dispatch(to, text, "utf-8");
        } catch (SmsException e) {
            throw new NotifyFailedException(to, e);  // 错误模型也一起翻译
        }
    }
}

与邻近模式的区别

模式目的接口
Adapter转换接口,让不兼容的能对接变成调用方期望的形状
Facade简化入口,降低客户端认知负担新开一个更简单的接口
Decorator在保持接口的前提下叠加行为接口不变
Proxy同一接口的替身,控制访问接口不变
Bridge抽象与实现各自独立扩展两侧都是自定义的
适配器应当薄且可测:转换规则集中在一处,用桩替换第三方即可单测。如果适配器里开始出现重试编排、缓存策略、业务判断,说明它已经越界成服务层,该把那些逻辑挪到更合适的位置。
适配器的有效范围通常只覆盖一个方向。上下游都需要转换时,写两个方向明确的适配器比写一个双向类更好维护:双向类容易把两套模型揉成一团,最后看不出谁在依赖谁。

易错点

  • 适配器里塞重试与业务判断:职责越界,两处逻辑都要维护
  • 第三方异常原样穿透:调用方被迫依赖第三方的异常模型,换供应商就全量改字段
  • 只包装不收敛:每处业务代码各写一次调用细节,适配器形同虚设
  • 适配器随第三方版本频繁修改:缺少一层内部模型,外部字段直接渗进领域代码

数据来源与参考

  • 《设计模式》(GoF)· Adapter
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌