【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开发干货

相关推荐
asdfg12589632 小时前
JS中的闭包应用
开发语言·前端·javascript
kirk_wang2 小时前
Flutter 导航锁踩坑实录:从断言失败到类型转换异常
前端·javascript·flutter
梦里不知身是客112 小时前
spark中如何调节Executor的堆外内存
大数据·javascript·spark
静小谢3 小时前
前后台一起部署,vite配置笔记base\build
前端·javascript·笔记
用户47949283569153 小时前
改了CSS刷新没反应-你可能不懂HTTP缓存
前端·javascript·面试
wangan0944 小时前
不带圆圈的二叉树
java·前端·javascript
JohnYan4 小时前
Bun技术评估 - 22 Stream
javascript·后端·bun
Aevget4 小时前
界面控件DevExpress JS & ASP.NET Core v25.1 - 全新的Stepper组件
javascript·asp.net·界面控件·devexpress·ui开发
林希_Rachel_傻希希4 小时前
手写Promise最终版本
前端·javascript·面试
该用户已不存在4 小时前
Node.js后端开发必不可少的7个核心库
javascript·后端·node.js