一、什么是适配器模式?
适配器模式(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)
现在,我们需要集成两个第三方的支付服务:PayPal
和 Stripe
。不幸的是,它们的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)
现在,轮到我们的主角------适配器登场了。我们将为 Ios
和 Android
分别创建一个适配器。
为 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
类可以无缝地使用任何一种支付方式,而完全不需要知道 Ios
或 Android
的内部细节。
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开发干货