【TS 设计模式完全指南】用适配器模式优雅地“兼容”一切

一、什么是适配器模式?

适配器模式(Adapter Pattern)是一种结构型设计模式 ,它的核心思想是:将一个类的接口转换成客户端所期望的另一个接口。 这使得原本因接口不兼容而无法协同工作的类可以一起工作。

二、适配器模式的核心组件

  • 目标 (Target) :这是客户端代码所期待和依赖的接口。在TypeScript中,我们通常用 interface 来定义它。
  • 被适配者 (Adaptee):这是已经存在的、但接口与目标不兼容的类或对象。它是"需要被适配"的角色。
  • 适配器 (Adapter) :这是模式的核心。它实现了 目标 (Target) 接口,并在内部持有对 被适配者 (Adaptee) 的引用。当客户端调用适配器的方法时,适配器会将其转换为对被适配者方法的调用。

三、示例:构建一个支付适配器

3.1 定义目标接口 (Target)

这是我们系统内部期望的支付接口,简洁明了。

typescript 复制代码
// Target: 我们系统期望的支付接口
interface PaymentProcessor {
    processPayment(amount: number): void;
}

我们的客户端代码会像这样使用它:

typescript 复制代码
class Store {
    private paymentProcessor: PaymentProcessor;

    constructor(processor: PaymentProcessor) {
        this.paymentProcessor = processor;
    }

    purchaseItem(price: number) {
        console.log(`准备购买一件价格为 ${price} 的商品...`);
        this.paymentProcessor.processPayment(price);
    }
}

3.2 引入"不兼容"的被适配者 (Adaptee)

现在,我们需要集成两个第三方的支付服务:PayPalStripe。不幸的是,它们的API设计和我们的 PaymentProcessor 完全不同。

typescript 复制代码
// Adaptee 1: Ios 的支付服务
class IosPaymentGateway {
    public sendPayment(total: number, currency: string): void {
        console.log(`Ios平台 支付了 ${currency} ${total}`);
    }
}

// Adaptee 2: android 的支付服务
class AndroidGateway {
    public submitTransaction(value: number, description: string): boolean {
        console.log(`android 平台 支付了 ${description}, 金额: ${value}`);
        return true; // 表示交易成功
    }
}
  • 可以看到ios平台和Android平台的支付参数不一致

3.3 创建适配器 (Adapter)

现在,轮到我们的主角------适配器登场了。我们将为 IosAndroid 分别创建一个适配器。

为 Ios 创建适配器:

typescript 复制代码
// Adapter for Ios
class IosAdapter implements PaymentProcessor {
    private iosGateway: IosPaymentGateway;

    constructor() {
        this.iosGateway = new IosPaymentGateway();
    }

    processPayment(amount: number): void {
        // 将我们简单的 processPayment 调用,转换为复杂的 sendPayment 调用
        console.log('适配器正在转换 ios 支付请求...');
        this.iosGateway.sendPayment(amount, 'USD');
    }
}

为 Android 创建适配器:

typescript 复制代码
// Adapter for Android
class AndroidAdapter implements PaymentProcessor {
    private androidGateway: AndroidGateway;

    constructor() {
        this.androidGateway = new AndroidGateway();
    }

    processPayment(amount: number): void {
        // 将 processPayment 调用,转换为 submitTransaction 调用
        console.log('适配器正在转换 android 支付请求...');
        this.androidGateway.submitTransaction(amount, '商品购买');
    }
}

3.4 将它们组合在一起

现在,我们的 Store 类可以无缝地使用任何一种支付方式,而完全不需要知道 IosAndroid 的内部细节。

typescript 复制代码
// 使用 Ios 支付
const iosAdapter = new IosAdapter();
const storeWithPayPal = new Store(iosAdapter);
storeWithPayPal.purchaseItem(100);

console.log('\n' + '='.repeat(30) + '\n');

// 切换到 Android 支付,Store 类代码无需任何修改!
const androidAdapter = new AndroidAdapter();
const storeWithStripe = new Store(androidAdapter);
storeWithStripe.purchaseItem(75);

运行结果:

erlang 复制代码
准备购买一件价格为 100 的商品...
适配器正在转换 ios 支付请求...
Ios平台 支付了 USD 100

==============================

准备购买一件价格为 75 的商品...
适配器正在转换 android 支付请求...
android 平台 支付了 商品购买, 金额: 75

为了方便大家学习和实践,本文的所有示例代码和完整项目结构都已整理上传至我的 GitHub 仓库。欢迎大家克隆、研究、提出 Issue,共同进步!

📂 核心代码与完整示例: GoF

总结

如果你喜欢本教程,记得点赞+收藏!关注我获取更多JavaScript/TypeScript开发干货

相关推荐
三脚猫的喵2 小时前
微信小程序中实现AI对话、生成3D图像并使用xr-frame演示
前端·javascript·ai作画·微信小程序
炒毛豆2 小时前
移动端响应式px转换插件PostCSS的使用~
前端·javascript·postcss
Swift社区3 小时前
为什么 socket.io 客户端在浏览器能连上,但在 Node.js 中报错 transport close?
javascript·node.js
wordbaby3 小时前
用 window.matchMedia 实现高级响应式开发:API 全面解析与实战技巧
前端·javascript
薄雾晚晴3 小时前
Rspack 实战,构建流程升级:自动版本管理 + 命令行美化 + dist 压缩,一键输出生产包
前端·javascript
Running_slave3 小时前
位运算左移右移应该怎么玩?
前端·javascript·算法
薄雾晚晴3 小时前
Rspack 性能优化实战:JS/CSS 压缩 + 代码分割,让产物体积直降 40%
前端·javascript
秃顶老男孩.3 小时前
web中的循环遍历
开发语言·前端·javascript
叫我阿柒啊4 小时前
从Java全栈到前端框架的实战之路
java·数据库·微服务·typescript·前端框架·vue3·springboot