适配器模式通过封装或继承将不兼容接口转译为统一目标接口(如NotificationSender),使客户端仅依赖抽象、不耦合具体SDK;常用对象适配器方式,各渠道适配器持有对应SDK实例并实现send(userId, content)方法,职责单一、易于扩展与测试。

适配器模式通过在不兼容的接口之间插入一个“翻译层”,让调用方只面向统一接口编程,而把具体实现细节交给适配器去桥接。它不修改原有类,也不强迫第三方 SDK 改接口,而是用封装或继承的方式,把 Adaptee 的方法调用“转译”成 Target 接口要求的形式。
核心是定义统一目标接口
先明确客户端真正需要什么——不是钉钉 sendMarkdown、不是企微 message().send(),而是简单一句:send(userId, content)。这个抽象就是 Target:
- 定义清晰、稳定、与业务强相关(比如 NotificationService 只关心“发通知”,不关心渠道细节)
- 通常是一个 interface,如
NotificationSender - 所有适配器都实现它,保证后续可多态使用(例如
List<NotificationSender>遍历发送)
用对象适配器封装已有 SDK
这是最常用、最推荐的方式:适配器内部持有被适配对象(Adaptee),通过组合转发调用:
- 钉钉适配器里 new 一个
DingTalkClient,在send()中调用它的sendMarkdown(...) - 企微适配器里持有一个
WeCom实例,在send()中构造TextMessage并链式调用send() - 飞书适配器用 Builder 构建
LarkMsg,再调用pushText() - 每个适配器只负责“翻译”,不承担业务逻辑(如重试、日志、限流)——这些可统一加在调用方或装饰器中
避免直接耦合,支持灵活替换
一旦有了适配器,原始 NotificationService 就不再依赖任何具体 SDK:
立即学习“Java免费学习笔记(深入)”;
- 构造时传入
NotificationSender实例,而不是 new 某个 SDK 类 - 换渠道只需替换适配器实现(比如从
DingTalkAdapter换成SlackAdapter),无需动业务代码 - 新增渠道只要写一个新适配器类,实现同一个接口,系统自动识别
- 单元测试更简单:可以 mock 掉整个
NotificationSender,不用启动真实 SDK
不碰源码,复用即安全
第三方 SDK 往往无法修改,老系统接口又不能轻易动——适配器正好卡在这个缝隙里:
- 你不需要反编译、打补丁或 fork 修改 SDK 源码
- 也不用说服合作方统一接口标准
- 所有转换逻辑集中在适配器类中,职责单一、边界清晰、便于维护
- 如果某 SDK 升级导致方法签名变化,只需改对应适配器,影响范围可控


















