Adapter (or Wrapper) is a structural design pattern that allows objects with incompatible interfaces to work together.
Purpose and Use Case
Use the Adapter pattern when you want to use an existing class or third-party library whose interface doesn't match the rest of your application code. It's ideal for keeping the Open/Closed Principle (SOLIDGlosarioSOLIDAcrónimo de cinco principios de diseño orientado a objetos y programación diseñados para hacer que el software sea más comprensible, flexible y mantenible: S - Single Responsibility Principle (Responsabilidad Única) O - Open/Closed Principle (Abierto/Cerrado) L - Liskov Substitution Principle (Sustitución de Liskov) I - Interface Segregation Principle (Segregación de Interfaz) D - Dependency Inversion Principle (Inversión de Dependencias) Ver término completo →) and avoiding duplicated code (DRYGlosarioDRY (Don't Repeat Yourself)Principio fundamental de diseño de software formulado por Andy Hunt y Dave Thomas. Establece que toda pieza de conocimiento o lógica debe tener una representación única, no ambigua y definitiva en el sistema para evitar duplicidad y facilitar el mantenimiento.Ver término completo →).
Unlike the Decorator Pattern (which adds new responsibilities), the Adapter solely translates an object's interface to match the client's expectations.
Pattern Structure
- Client: Contains the existing business logic of the application.
- Client Interface (Target): Declares the protocol that other classes must follow to collaborate with the client.
- Adaptee: Incompatible third-party class or service you want to use.
- Adapter: Wrapper class that implements the client interface and translates calls to the adaptee.
Execution Flow
- Invocation: Client calls a method on the target interface via the Adapter object.
- Translation: The Adapter converts received parameters to the format expected by the adaptee.
- Execution: The Adapter delegates the actual call to the Adaptee and returns the processed response to the client.
Real Implementation Examples
// Interface expected by the application
interface PaymentProcessor {
processPayment(amountInCents: number): Promise<boolean>;
}
// Incompatible legacy third-party service
class LegacyStripeSDK {
public makeCharge(dollars: number, currency: string): boolean {
console.log(`Charging $${dollars} ${currency} via LegacyStripe`);
return true;
}
}
// Adapter unifying the interface
class StripePaymentAdapter implements PaymentProcessor {
private legacyStripe: LegacyStripeSDK;
constructor(legacyStripe: LegacyStripeSDK) {
this.legacyStripe = legacyStripe;
}
public async processPayment(amountInCents: number): Promise<boolean> {
const dollars = amountInCents / 100;
return this.legacyStripe.makeCharge(dollars, "USD");
}
}
// Client usage:
const adapter: PaymentProcessor = new StripePaymentAdapter(new LegacyStripeSDK());
adapter.processPayment(2500); // Processes 25.00 USD transparently