6. 适配器模式(Adapter)
6. 适配器模式(Adapter)
问题:已有接口和目标接口不兼容,不想改老代码。
核心:写一个适配层,把旧接口转换成新接口。
// 旧接口:华氏温度
class OldWeatherAPI {
getTemp(): number { return 98.6; }
}
// 适配器:转成摄氏度
class CelsiusAdapter {
#oldAPI: OldWeatherAPI;
constructor(api: OldWeatherAPI) { this.#oldAPI = api; }
getTempC(): number { return (this.#oldAPI.getTemp() - 32) * 5 / 9; }
}
const adapter = new CelsiusAdapter(new OldWeatherAPI());
console.log(adapter.getTempC().toFixed(1)); // 37.0package adapter
// 旧接口:华氏温度
type OldWeatherAPI struct{}
func (o OldWeatherAPI) GetTempF() float64 { return 98.6 }
// 目标接口:摄氏温度
type CelsiusProvider interface {
GetTempC() float64
}
// 适配器
type CelsiusAdapter struct {
old OldWeatherAPI
}
func NewCelsiusAdapter(old OldWeatherAPI) CelsiusProvider {
return &CelsiusAdapter{old: old}
}
func (a *CelsiusAdapter) GetTempC() float64 {
return (a.old.GetTempF() - 32) * 5 / 9
}实战场景
- 老接口迁移:旧系统返回字段名、单位或错误结构与新系统不一致,适配器把旧响应转换成新接口期望的格式。
- 第三方 SDK 包装:支付、短信、地图、对象存储 SDK 的方法风格各不相同,适配成项目内部统一接口。
- 单位转换:温度、货币、长度、时区、文件大小等外部数据进入系统时,适配器统一转换成内部标准单位。
- 数据库替换:把旧 repository 接口适配到新的 ORM 或查询层,让业务代码不用一次性跟着重写。
- UI 组件封装:不同组件库的
value/onChange、modelValue/update:modelValue、表单校验接口不一致,可以写适配层统一。 - 消息格式桥接:Kafka、RabbitMQ、Webhook、Server-Sent Events 的消息结构不同,适配成内部统一事件对象。
- Auth 集成:OAuth、JWT、Session、企业 SSO 返回的用户信息格式不同,适配成统一的
CurrentUser。 - 文件导入:不同客户上传的 CSV 列名和编码不一致,适配器把它们转换成标准领域对象。
- 测试替身:真实服务接口很复杂,测试中用适配器把简单 fake 对象包装成生产接口。
- 渐进式重构:新旧模块并存时,先用适配器隔离差异,等调用方稳定后再慢慢替换内部实现。