Adapter (Adaptador o Wrapper) es un patrón de diseño estructural que permite la colaboración entre objetos que de otro modo serían incompatibles debido a diferencias en sus interfaces.
💡 Ver Caso Práctico: Ejemplo Práctico del Patrón Adapter
Propósito y Caso de Uso
Utiliza el patrón Adapter cuando quieras utilizar una clase existente o una librería de terceros cuya interfaz no coincida con el resto del código de tu aplicación. Es ideal para mantener el principio de Abierto/Cerrado (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 →) y evitar el código duplicado (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 →).
A diferencia del Patrón Decorator (que añade nuevas responsabilidades), el Adapter únicamente traduce la interfaz de un objeto para adaptarla a las necesidades del cliente.
Estructura del Patrón
- Cliente: Contiene la lógica de negocio existente de la aplicación.
- Interfaz Cliente (Target): Declara el protocolo que las demás clases deben seguir para colaborar con el cliente.
- Servicio Adaptado (Adaptee): Clase o servicio de terceros incompatible que se desea utilizar.
- Adaptador (Adapter): Clase envoltorio que implementa la interfaz cliente y traduce las llamadas hacia el servicio adaptado.
Flujo de Funcionamiento
- Invocación: El cliente llama a un método de la interfaz objetivo a través del objeto Adaptador.
- Traducción: El Adaptador convierte los parámetros recibidos al formato que espera la librería de terceros.
- Ejecución: El Adaptador delega la llamada real al objeto adaptado (Adaptee) y retorna la respuesta procesada al cliente.
Ejemplos de Implementación Reales
// Interfaz esperada por la aplicación
interface PaymentProcessor {
processPayment(amountInCents: number): Promise<boolean>;
}
// Servicio de terceros antiguo o incompatible
class LegacyStripeSDK {
public makeCharge(dollars: number, currency: string): boolean {
console.log(`Cobrando $${dollars} ${currency} mediante LegacyStripe`);
return true;
}
}
// Adaptador que unifica la interfaz
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");
}
}
// Uso en el cliente:
const adapter: PaymentProcessor = new StripePaymentAdapter(new LegacyStripeSDK());
adapter.processPayment(2500); // Procesa 25.00 USD transparentemente