Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Patrones de Diseño Estructurales

Adapter

Compatibilidad entre interfaces incompatibles

Universidad Nacional de Rio Negro - Sede Andina

Definición

El patrón Adapter (también conocido como Wrapper) permite que clases con interfaces incompatibles trabajen juntas, convirtiendo la interfaz de una clase en otra que el cliente espera. Actúa como un “traductor” entre dos interfaces, permitiendo que objetos con interfaces incompatibles colaboren.

Origen e Historia

El Adapter fue documentado por Gang of Four en 1994. Tiene raíces en el concepto de “adapters” físicos (como adaptadores de electricidad que permiten usar dispositivos en diferentes regiones). En software, se popularizó para resolver la integración de código heredado con código nuevo.

Motivación

Surge cuando:

Contexto

Escenario típico:

Anatomía:

Cuando aplica

Usá Adapter cuando:

Cuando no aplica

Evitá Adapter cuando:

Consecuencias de su uso

Positivas

Negativas

Alternativas

PatrónPropósitoCuando
BridgeDesacoplar abstracción de implementaciónMúltiples dimensiones
DecoratorAgregar responsabilidades dinámicamenteExtender comportamiento
FacadeSimplificar interfaz complejaSistemas complejos

Estructura

Problema

// Cliente espera esta interfaz
public interface TargetaConector {
    void conectar();
    void desconectar();
}

// Dispositivo antiguo con interfaz diferente
public class DispositivoAntiguoEuropeo {
    public void enchufar() {
        System.out.println("Enchufado con conector europeo (2 pines)");
    }
    
    public void desenchufar() {
        System.out.println("Desenchufado desde conector europeo");
    }
}

// ❌ Problema: No puedo usar directamente
TargetaConector conector = new DispositivoAntiguoEuropeo();  // Error de compilación!

Solución

/**
 * Adapter que convierte DispositivoAntiguoEuropeo 
 * a la interfaz TargetaConector.
 */
public class AdaptadorEuropaAmerica implements TargetaConector {
    private DispositivoAntiguoEuropeo dispositivo;
    
    public AdaptadorEuropaAmerica(DispositivoAntiguoEuropeo dispositivo) {
        this.dispositivo = dispositivo;
    }
    
    @Override
    public void conectar() {
        dispositivo.enchufar();
    }
    
    @Override
    public void desconectar() {
        dispositivo.desenchufar();
    }
}

// ✅ Ahora funciona
DispositivoAntiguoEuropeo tv = new DispositivoAntiguoEuropeo();
TargetaConector conector = new AdaptadorEuropaAmerica(tv);
conector.conectar();      // Funciona como se esperaba
conector.desconectar();

Diagramas

Diagrama de Clases

Diagrama de Secuencia

Ejemplos

Ejemplo 1: Integración de Sistemas de Notificación

// Interfaz que espera el cliente (nuevo sistema)
public interface SistemaNotificacionModerno {
    void enviarNotificacion(String mensaje);
}

// Sistema antiguo que no queremos modificar
public class SistemaNotificacionAntiguoFax {
    public void enviarFax(String numero, String contenido) {
        System.out.println("Fax enviado a " + numero + ": " + contenido);
    }
}

// Adapter que traduce notificación moderna a fax antiguo
public class AdaptadorNotificacionAFax implements SistemaNotificacionModerno {
    private SistemaNotificacionAntiguoFax sistemaFax;
    private String numeroFaxPorDefecto;
    
    public AdaptadorNotificacionAFax(SistemaNotificacionAntiguoFax sistemaFax, 
                                      String numeroFax) {
        this.sistemaFax = sistemaFax;
        this.numeroFaxPorDefecto = numeroFax;
    }
    
    @Override
    public void enviarNotificacion(String mensaje) {
        sistemaFax.enviarFax(numeroFaxPorDefecto, mensaje);
    }
}

// Cliente que usa la interfaz moderna
public class CentroNotificaciones {
    private SistemaNotificacionModerno sistema;
    
    public CentroNotificaciones(SistemaNotificacionModerno sistema) {
        this.sistema = sistema;
    }
    
    public void notificar(String mensaje) {
        sistema.enviarNotificacion(mensaje);
    }
}

// Uso
SistemaNotificacionAntiguoFax fax = new SistemaNotificacionAntiguoFax();
SistemaNotificacionModerno adaptado = new AdaptadorNotificacionAFax(fax, "+549111234567");
CentroNotificaciones centro = new CentroNotificaciones(adaptado);

centro.notificar("Alerta de seguridad");
// Salida: Fax enviado a +549111234567: Alerta de seguridad

Variantes

Adapter de Clase (Herencia):

public class AdaptadorPorHerencia extends DispositivoAntiguoEuropeo 
    implements TargetaConector {
    
    @Override
    public void conectar() {
        this.enchufar();
    }
    
    @Override
    public void desconectar() {
        this.desenchufar();
    }
}

Ejercicios

Resumen

El patrón Adapter resuelve problemas de incompatibilidad entre interfaces proporcionando una clase intermediaria que traduce llamadas. Es fundamental en integración de sistemas heterogéneos y reutilización de código existente sin modificación. Aunque introduce indirección, su beneficio en separación de concerns y flexibilidad lo hacen invaluable en arquitecturas empresariales.

Próximo paso

Para seguir, conviene pasar a el material siguiente, donde el recorrido continúa sobre esta base.