前言
你好啊,我是你的人类朋友
在工作中,可能会遇到这样的情况:
一个封装好的工作流只接收固定参数 A 和 B,分别是用于取数据的 url 和数据存储位置。
但当需要同时处理两方数据时,你会如何解决?
是修改原有代码,让他可以接受多组参数,还是有更优雅的方案?
文章会给出使用适配器模式,在不修改原有代码的情况下,实现同时处理多组参数的方案。
正文
适配器模式通过创建一个中间层来转换接口,使得不兼容的接口能够协同工作,而不需要修改原有代码!
小贴士,这符合了开闭原则,也就是对修改关闭,对扩展开放。
一、实际应用场景
假设我们有一个已封装的工作流,这边就用 js 函数来表示好了,它只接受特定格式的参数:
javascript
/* 原有工作流开始 - 不能修改,因为被很多地方使用了 */
class Workflow {
/**
* 原有工作流的执行方法
* @param {string} source - 数据来源地址
* @param {string} target - 数据存储位置
*/
execute(source, target) {
console.log(`从 ${source} 取数据,存储到 ${target}`)
// 实际的数据处理逻辑
}
}
/* 原有工作流结束 */
/* 数据定义开始 */
const source1 = '数据库A' // 第一组数据来源
const target1 = '存储X' // 第一组数据存储位置
const source2 = 'API_B' // 第二组数据来源
const target2 = '存储Y' // 第二组数据存储位置
/* 数据定义结束 */
/* 适配器模式实现开始 */
class WorkflowAdapter {
constructor(workflow) {
this.workflow = workflow // 持有原有工作流的实例
}
/**
* 新接口:同时处理多组数据源和存储位置
* @param {string[]} sources - 数据来源数组
* @param {string[]} targets - 数据存储位置数组
*/
executeMultiple(sources, targets) {
// 遍历所有数据源,逐个调用原有工作流处理
sources.forEach((source, index) => {
const target = targets[index] // 取到对应的存储位置
this.workflow.execute(source, target) // 调用原有工作流的执行方法
})
}
}
/* 适配器模式实现结束 */
/* 使用示例开始 */
// 创建原有工作流实例
const originalWorkflow = new Workflow()
// 创建适配器,包装原有工作流
const workflowAdapter = new WorkflowAdapter(originalWorkflow)
// 使用适配器的新接口同时处理多组参数
workflowAdapter.executeMultiple([source1, source2], [target1, target2])
/* 使用示例结束 */
输出如下:
text
从 数据库A 取数据,存储到 存储X
从 API_B 取数据,存储到 存储Y
二、其他场景
下面的各个场景留一个印象即可,后续真遇到了吗,这个不起眼的"印象"就价值连城了
📦 第三方服务集成
当接入不同供应商的 API 时,
比如支付接口(微信支付、支付宝)、
地图服务(高德、百度)、短信服务等。每个服务商的接口规范各不相同,通过适配器统一成标准接口,业务代码无需关心底层实现。
🔄 数据格式转换
老系统使用 XML 格式,新系统使用 JSON 格式。
适配器在中间进行格式转换,让新旧系统能够无缝通信,避免大规模数据迁移。
📡 API 版本兼容
当 API 升级时,为了保证老用户的正常使用,通过适配器保持向下兼容。
新版本接口变化时,适配器负责将老接口调用转换为新接口格式。
总之,适配就完事了!!
🖨️ 设备驱动适配
打印机、扫描仪等外设厂商各异,驱动接口不同。
适配器提供统一的打印、扫描接口,应用程序无需为每个设备编写特定代码。
🌐 协议转换
不同系统 间使用不同通信协议(HTTP、WebSocket、TCP),
适配器负责协议转换,让使用不同协议的系统能够相互通信。
💾 数据库兼容
应用程序需要支持多种数据库(MySQL、PostgreSQL、MongoDB)。
适配器提供统一的数据操作接口,底层自动适配不同数据库的 SQL 方言。
所以,当你在为各个数据库写不同的 SQL 语句时,脑子里面应该有一个适配器不断横跳的画面!
📱 跨平台兼容
同一功能在不同平台(Web、iOS、Android)有不同实现方式。
适配器抹平平台差异,提供一致的调用接口。
最后
最后回答一下,什么是适配器模式?
适配器模式是一种结构型设计模式,它通过创建一个中间适配器来转换接口,使得原本不兼容的类或接口能够协同工作,而无需修改它们的原始代码。
假如一个接口被多处地方使用,修改它会导致很多地方的代码都需要修改,这是不希望看到的。
而使用适配器模式,只需要修改适配器的代码,而不会影响到原有代码的使用。
这就是适配器模式的优势所在!😆