Logo
Section 1 / 19

理解适配器模式

将不兼容的 API 和服务适配为一致的接口,而无需重写客户端逻辑。

导入

理解适配器模式

将不兼容的 API 和服务适配为一致的接口,而无需重写客户端逻辑。

...
The adapter lies between the client and the adaptee, translating calls and relaying results

代码示例

Node.js

1// External service (incompatible interface) 2class ThirdPartyBilling { 3 processPayment(cents) { 4 console.log(`ThirdPartyBilling charged ${cents} cents`); 5 return Promise.resolve({ ok: true }); 6 } 7} 8 9// Internal service (also incompatible) 10class InternalBilling { 11 chargeUSDollars(dollars) { 12 console.log(`InternalBilling charged $${dollars}`); 13 return { success: true }; 14 } 15} 16 17// Adapter interface: standardize to `charge(amountInDollars)` 18class BillingAdapter { 19 constructor(billingClient, type) { 20 this.client = billingClient; 21 this.type = type; 22 } 23 24 async charge(amountInDollars) { 25 if (this.type === 'third-party') { 26 const cents = amountInDollars * 100; 27 const result = await this.client.processPayment(cents); 28 return result.ok; 29 } 30 31 if (this.type === 'internal') { 32 const result = this.client.chargeUSDollars(amountInDollars); 33 return result.success; 34 } 35 36 throw new Error('Unknown billing client'); 37 } 38} 39 40// Usage 41async function checkout(amount, adapter) { 42 const ok = await adapter.charge(amount); 43 if (ok) { 44 console.log('Charge succeeded'); 45 } else { 46 console.log('Charge failed'); 47 } 48} 49 50const thirdParty = new BillingAdapter(new ThirdPartyBilling(), 'third-party'); 51const internal = new BillingAdapter(new InternalBilling(), 'internal'); 52 53checkout(25, thirdParty); 54checkout(25, internal);

TypeScript

1// External service (incompatible interface) 2class ThirdPartyBilling { 3 processPayment(cents: number): Promise<{ ok: boolean }> { 4 console.log(`ThirdPartyBilling charged ${cents} cents`); 5 return Promise.resolve({ ok: true }); 6 } 7} 8 9// Internal service (also incompatible) 10class InternalBilling { 11 chargeUSDollars(dollars: number): { success: boolean } { 12 console.log(`InternalBilling charged $${dollars}`); 13 return { success: true }; 14 } 15} 16 17interface BillingClient { 18 charge(amountInDollars: number): Promise<boolean>; 19} 20 21// Adapter interface: standardize to `charge(amountInDollars)` 22class BillingAdapter implements BillingClient { 23 constructor( 24 private client: any, 25 private type: 'third-party' | 'internal' 26 ) {} 27 28 async charge(amount: number): Promise<boolean> { 29 if (this.type === 'third-party') { 30 const cents = amount * 100; 31 const result = await this.client.processPayment(cents); 32 return result.ok; 33 } 34 35 if (this.type === 'internal') { 36 const result = this.client.chargeUSDollars(amount); 37 return result.success; 38 } 39 40 throw new Error('Unknown billing client'); 41 } 42} 43 44// Usage 45async function checkout(amount: number, adapter: BillingClient) { 46 const ok = await adapter.charge(amount); 47 console.log(ok ? 'Charge succeeded' : 'Charge failed'); 48} 49 50const thirdParty = new BillingAdapter(new ThirdPartyBilling(), 'third-party'); 51const internal = new BillingAdapter(new InternalBilling(), 'internal'); 52 53checkout(25, thirdParty); 54checkout(25, internal);
...
The adapter unifies third-party and internal billing under one charge() interface.

装饰器模式:在不修改核心逻辑的情况下扩展行为

统一 HTTP 客户端响应