什么是适配器模式?

适配器模式(Adapter Pattern)是一种结构型设计模式,它能让接口不兼容的对象相互合作。当一个类(或对象)的接口与客户端期望的接口不一致时,适配器可以作为 “中间层”,将原有接口转换为客户端需要的接口,从而解决接口不匹配的问题。

适配器模式的核心是 “转换接口”,而非修改原有接口或客户端代码,常用于整合遗留系统、第三方库等已有组件。

适配器模式的核心角色

  1. 目标接口(Target):客户端期望的接口,定义了客户端可以调用的方法。
  2. 适配者(Adaptee):已存在的、接口不兼容的类(或对象),需要被适配。
  3. 适配器(Adapter):实现目标接口,内部持有适配者的引用,将目标接口的调用转换为适配者的接口调用。

JavaScript 实现适配器模式示例:支付接口适配

以下以 “支付系统整合” 为例,实现适配器模式。场景是:现有系统需要接入两个支付渠道(支付宝和微信支付),但它们的接口格式不同(支付宝用 payMoney(amount),微信用 wechatPay(price)),客户端希望用统一的 pay(amount) 方法调用支付功能。

代码实现 - javascript
// -------------- 1. 适配者(Adaptee):现有支付渠道(接口不兼容)--------------
// 支付宝支付(原有接口:payMoney(金额))
class Alipay {
  payMoney(amount) {
    console.log(`支付宝支付:${amount}元`);
    return { success: true, orderId: `alipay_${Date.now()}` };
  }
}

// 微信支付(原有接口:wechatPay(价格))
class WechatPay {
  wechatPay(price) {
    console.log(`微信支付:${price}元`);
    return { code: 0, tradeNo: `wechat_${Date.now()}` };
  }
}

// -------------- 2. 目标接口(Target):客户端期望的统一接口 --------------
// 支付适配器基类(定义客户端需要的接口)
class PayAdapter {
  pay(amount) {
    throw new Error("子类必须实现 pay 方法");
  }
}

// -------------- 3. 具体适配器:适配支付宝和微信支付 --------------
// 支付宝适配器(将 pay(amount) 转换为 payMoney(amount))
class AlipayAdapter extends PayAdapter {
  constructor() {
    super();
    this.alipay = new Alipay(); // 持有适配者实例
  }

  pay(amount) {
    // 调用支付宝的原有接口,并转换返回格式(可选)
    const result = this.alipay.payMoney(amount);
    return { success: result.success, orderNo: result.orderId }; // 统一返回格式
  }
}

// 微信支付适配器(将 pay(amount) 转换为 wechatPay(amount))
class WechatPayAdapter extends PayAdapter {
  constructor() {
    super();
    this.wechatPay = new WechatPay(); // 持有适配者实例
  }

  pay(amount) {
    // 调用微信的原有接口,并转换返回格式(可选)
    const result = this.wechatPay.wechatPay(amount);
    return { success: result.code === 0, orderNo: result.tradeNo }; // 统一返回格式
  }
}

// -------------- 4. 客户端使用 --------------
// 客户端函数:只依赖目标接口(PayAdapter),无需关心具体支付渠道
function checkout(adapter, amount) {
  console.log(`开始支付,金额:${amount}元`);
  const result = adapter.pay(amount);
  if (result.success) {
    console.log(`支付成功,订单号:${result.orderNo}`);
  } else {
    console.log("支付失败");
  }
}

// 使用支付宝支付(通过适配器)
const alipayAdapter = new AlipayAdapter();
checkout(alipayAdapter, 199);
// 输出:
// 开始支付,金额:199元
// 支付宝支付:199元
// 支付成功,订单号:alipay_1731580800000

// 使用微信支付(通过适配器)
const wechatAdapter = new WechatPayAdapter();
checkout(wechatAdapter, 299);
// 输出:
// 开始支付,金额:299元
// 微信支付:299元
// 支付成功,订单号:wechat_1731580800001

代码说明

  1. 适配者(Alipay、WechatPay):代表已存在的支付渠道,它们的接口(payMoneywechatPay)与客户端期望的 pay 不一致,是需要被适配的对象。
  2. 目标接口(PayAdapter):定义了客户端需要的统一接口 pay(amount),所有适配器都需实现该接口。
  3. 适配器(AlipayAdapter、WechatPayAdapter)
    • 内部持有适配者的实例(如 Alipay),实现 pay 方法。
    • 在 pay 方法中,将客户端的调用转换为适配者的接口调用(如 alipay.payMoney(amount)),并可选地统一返回格式(如将支付宝的 orderId 和微信的 tradeNo 统一为 orderNo)。
  4. 客户端:通过适配器调用支付功能,只需依赖 PayAdapter 接口,无需知道具体支付渠道的差异,实现了解耦。

适配器模式的优势

  • 兼容性:解决了接口不匹配的问题,使原有组件(如第三方库、遗留系统)能与新系统协同工作。
  • 复用性:无需修改原有组件代码,即可复用其功能,保护了已有投资。
  • 灵活性:新增适配者时,只需新增对应的适配器,客户端代码无需修改,符合 “开闭原则”。

常见应用场景

  • 整合第三方库:如将不同日期库(Moment.js、Day.js)的接口适配为项目统一的日期处理接口。
  • 兼容旧系统:如将老系统的 getUserInfo(userId) 接口适配为新系统的 fetchUser({ id: userId }) 接口。
  • 跨平台适配:如在小程序中,将不同平台(微信、支付宝)的 API 适配为统一调用方式。

适配器模式的核心是 “兼容差异,无缝对接”,是系统整合时的重要工具。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐