适配器模式通过中间层将第三方短信服务接口统一为内部SmsService.send()标准接口,封装差异、隔离变化,仅需修改适配器和配置即可切换供应商。

适配器模式在整合第三方短信服务时,核心是把各家差异化的接口“翻译”成你系统内部统一调用的接口,不改原有业务逻辑,也不动第三方 SDK,靠一个中间层完成对接。
明确目标接口(你系统想要的调用方式)
先定义你业务代码里期望怎么发短信,比如:
-
SmsService.send(String phone, String templateId, Map
params) —— 所有渠道都走这个方法 - 参数语义清晰:手机号、模板 ID、变量内容(如验证码、订单号)
- 返回统一结构:成功/失败 + 业务标识(如 request_id),不暴露底层细节
封装每个第三方为适配者(已有但不兼容的类)
阿里云、腾讯云、亿美、互亿无线等服务商 SDK 或 HTTP API 各自有一套调用方式,它们就是适配者(Adaptee):
- 阿里云:需传
SignName、TemplateCode、TemplateParam,还要做签名和时间戳 - 腾讯云:用
PhoneNumberSet数组、TemplateID、TemplateParamSet,签名算法不同 - 中国网建(WebChinese):只支持简单 GET/POST,参数名是
Uid、Key、smsMob、smsText - 这些接口不能直接被业务代码调用,因为参数、命名、流程都不一致
编写适配器(桥接两者的关键实现)
为每个服务商写一个适配器类,它实现你的目标接口,并内部调用对应服务商的逻辑:
- 用对象适配器(推荐):适配器类实现
SmsService,构造时注入该服务商的客户端实例(如AliyunSmsClient) - 在
send()方法里,把统一参数转换成该服务商要求的格式,再调用其原生方法 - 例如:把
templateId映射为阿里云的TemplateCode,把params转成 JSON 字符串赋给TemplateParam - 异常统一包装:把各平台的网络错误、鉴权失败、模板未审核等,转为你的标准错误码(如
ERR_SMS_CHANNEL_UNAVAILABLE)
运行时动态切换与解耦设计
避免硬编码渠道选择,让系统更灵活:
- 用工厂或 Spring 的
@Qualifier根据配置加载对应适配器(如aliyun-sms、tencent-sms) - 像
platform-sms那样把适配器打成插件(plugin),启动时扫描加载,新增渠道无需重启主服务 - 配合策略模式:根据手机号号段、模板类型、失败重试结果,自动降级到备用渠道
- 关键操作异步化:业务只负责发任务进队列,由独立消费者调用适配器发送,隔离短信失败对主流程的影响
本质上,适配器不是为了“多写一层”,而是把变化锁在最小范围内——换短信供应商时,只动适配器和配置,业务代码一行不用改。


















