【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 分钟前
React setState 连续调用「丢更新」排查:批量更新与函数式更新
前端·javascript·react.js·react·usestate
come1123418 分钟前
Vue 2 与 Vue 3 语法区别及使用技巧
前端·javascript·vue.js
腻害兔29 分钟前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:ERP 企业资源模块,一个轻量级进销存的完整实现?
前端·javascript·vue.js·人工智能·前端框架·产品经理·ai编程
杨充34 分钟前
10.可测试性实战设计
设计模式·开源·代码规范
杨充42 分钟前
9.重构十二式的实战
设计模式·开源·代码规范
糖果店的幽灵1 小时前
langgraph的四种state解析
java·前端·javascript·langgraph
杨充1 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充1 小时前
2.面向对象的特性
设计模式
杨充1 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充1 小时前
8.反模式与坏味道
设计模式·开源·代码规范