# Propósito
El patrón Adapter convierte la interfaz de una clase en otra, que es la que esperan los clientes. Permite que clases con interfaces incompatibles trabajen juntas.
# Problema
El problema que resuelve es la incompatibilidad de interfaces. Surge cuando queremos usar una clase existente, pero su interfaz no se corresponde con la que necesitamos.
# Solución
La solución que propone el Adapter es:
-
Creación de un intermediario (Adapter): Implementa la interfaz que se requiere y envuelve la clase existente, traduciendo las llamadas a su interfaz.
-
Compatibilidad sin cambios en el código existente: Permite que el código existente funcione mediante nuevas interfaces, sin necesidad de modificarlo.
# Estructura
# Participantes
-
Target: Define la interfaz específica que usa el cliente, la que espera y entiende.
-
Adapter: Implementa la interfaz Target y encapsula una instancia de Adaptee. Adapta la interfaz de Adaptee a la interfaz Target.
-
Adaptee: La clase existente que necesita ser adaptada.
-
Client: Usa la interfaz Target.
# Cuándo Usarlo
Este patrón es recomendable cuando:
-
queremos usar una clase existente cuya interfaz no se ajusta a la que necesitamos.
-
debemos crear una clase reutilizable que coopera con clases no relacionadas o imprevistas.
# Ventajas
-
verified
Reutilización de Código
Permite reutilizar código existente, incluso si sus interfaces no coinciden.
-
verified
Separación de Código
El código de la aplicación se mantiene separado del código del adaptador.
-
verified
Flexibilidad
Se pueden agregar o eliminar adaptadores sin alterar el código existente.
# Desventajas
-
warning
Introduce complejidad
Agrega clases y objetos, lo que puede complicar el diseño.
-
warning
Rendimiento
Puede haber una pequeña baja en el rendimiento por la capa adicional.
# Ejemplo: Invocar una API externa
Debemos invocar un servicio externo que retorna el detalle de los impuestos calculados en el mes, la respuesta viene en formato XML. Eso lo debemos enviar al sistema interno de contabilidad, pero en formato JSON.
Problema
Hay una incompatibilidad en la comunicación, por un lado recibimos un XML y por el otro debemos enviar un JSON.
Solución planteada
Implementamos un Adapter, vamos a cambiar el formato de los datos de XML a JSON, para enviarlos al servicio interno de contabilidad.
# Código Java
Tenemos la clase XMLDataProvider, que se comunica con el sistema externo y retorna los datos en XML:
public class XMLDataProvider {
public String getXMLData() {
return "<result><month>March</month><total>100</total></result>";
}
}
Definimos la interfaz JSONDataProvider:
public interface JSONDataProvider {
String getJSONData();
}
Creamos el Adapter, que realiza la conversión de XML a JSON:
public class XMLToJSONAdapter implements JSONDataProvider {
private XMLDataProvider xmlDataProvider;
public XMLToJSONAdapter(XMLDataProvider xmlDataProvider) {
this.xmlDataProvider = xmlDataProvider;
}
public String getJSONData() {
String xmlStr = xmlDataProvider.getXMLData();
// Lógica para convertir XML a JSON...
return "{'result': {'month': 'March', 'total': 100}}";
}
}
# Mapeo Participantes
-
XMLDataProvider (Adaptee): Clase existente que provee datos en XML.
-
JSONDataProvider (Target): Interfaz esperada por el sistema.
-
XMLToJSONAdapter (Adapter): Realiza la conversión de XML a JSON.
-
Client (Client): Usa la interfaz Target.
# Conclusiones
Facilitó la integración de dos sistemas con formatos de datos incompatibles, un problema muy común en la integración de servicios.
# Patrones relacionados
Bridge
Estructura similar, pero Bridge separa interfaz de implementación.
Decorator
Decora otro objeto sin cambiar su interfaz.
Proxy
Define un representante o sustituto sin cambiar la interfaz.