Patrón Adaptador
El patrón adaptador (Adapter Pattern) actúa como un puente entre dos interfaces incompatibles y pertenece a los patrones de diseño estructurales. A través de un middleware (adaptador), convierte la interfaz de una clase en otra interfaz que el cliente espera, permitiendo que clases que originalmente no podían trabajar juntas cooperen.
Este patrón involucra una única clase que se encarga de añadir funcionalidades de interfaces independientes o incompatibles. Un ejemplo real: el lector de tarjetas actúa como adaptador entre la tarjeta de memoria y el portátil. Se inserta la tarjeta de memoria en el lector y este en el portátil, de modo que se puede leer la tarjeta de memoria a través del portátil.
Supongamos que hay un reproductor de audio que solo puede reproducir archivos MP3. Ahora necesitamos reproducir archivos VLC y MP4, lo cual se puede lograr creando un adaptador:
- Interfaz objetivo: Define una interfaz de reproductor de audio que pueda reproducir archivos en múltiples formatos.
- Clase adaptada (Adaptee): El reproductor de audio existente, que solo puede reproducir archivos MP3.
- Clase adaptadora (Adapter): Crea una nueva clase que implemente la interfaz objetivo y, internamente, utilice la clase adaptada para reproducir archivos MP3, agregando también soporte para archivos VLC y MP4.
Resumen
El patrón adaptador es un patrón de diseño de software que tiene como objetivo resolver problemas de compatibilidad entre diferentes interfaces.
Propósito: Convertir la interfaz de una clase en otra interfaz, de modo que las clases originalmente incompatibles puedan trabajar juntas.
Problema principal que resuelve: En un sistema de software, se necesita colocar objetos existentes en un nuevo entorno, pero la interfaz requerida por el nuevo entorno no coincide con la de los objetos existentes.
Escenarios de uso
- Se necesita usar una clase existente, pero su interfaz no cumple con los requisitos del sistema.
- Se desea crear una clase reutilizable que trabaje con varias clases no relacionadas (incluidas las que puedan introducirse en el futuro), las cuales pueden no tener una interfaz uniforme.
- Integrar una clase en otro sistema de clases mediante la conversión de interfaz.
Método de implementación
- Herencia o dependencia: Se recomienda usar la relación de dependencia en lugar de la herencia para mantener la flexibilidad.
Código clave
El adaptador hereda o depende de un objeto existente e implementa la interfaz objetivo requerida.
Ejemplos de aplicación
- Adaptador de voltaje: Convierte 110V a 220V para adaptarse a los estándares eléctricos de diferentes países.
- Conversión de interfaz: Por ejemplo, convertir la interfaz Enumeration de Java JDK 1.1 a la interfaz Iterator de JDK 1.2.
- Ejecución multiplataforma: Ejecutar programas de Windows en Linux.
- Conexión de base de datos: JDBC en Java interactúa con diferentes tipos de bases de datos mediante el patrón adaptador.
Ventajas
- Promueve la cooperación entre clases, incluso si no tienen una relación directa.
- Mejora la reutilización de las clases.
- Aumenta la transparencia de las clases.
- Proporciona una buena flexibilidad.
Desventajas
- El uso excesivo de adaptadores puede provocar una estructura del sistema desordenada, difícil de entender y mantener.
- En Java, dado que solo se puede heredar de una clase, solo se puede adaptar una clase, y la clase objetivo debe ser abstracta.
Recomendaciones de uso
- El patrón adaptador debe usarse con cautela, especialmente en la fase de diseño detallado; se utiliza más para resolver problemas en sistemas existentes.
- Cuando se considera modificar la interfaz de un sistema que funciona correctamente, el patrón adaptador es una opción adecuada.
De esta manera, el patrón adaptador puede expresar claramente su concepto central y su aplicación, evitando complejidades innecesarias.
Estructura
El patrón adaptador incluye los siguientes roles principales:
- Interfaz objetivo (Target): Define la interfaz que necesita el cliente.
- Clase adaptada (Adaptee): Define una interfaz ya existente que necesita ser adaptada.
- Clase adaptadora (Adapter): Implementa la interfaz objetivo y, mediante composición o herencia, invoca los métodos de la clase adaptada para lograr la interfaz objetivo.
Implementación
Tenemos unaMediaPlayerinterfaz y una clase de entidad que implementa laMediaPlayerinterfaz.AudioPlayer. De forma predeterminada,AudioPlayerpuede reproducir archivos de audio en formato mp3.
También tenemos otra interfazAdvancedMediaPlayery una clase de entidad que implementa laAdvancedMediaPlayerinterfaz. Esta clase puede reproducir archivos en formato vlc y mp4.
Queremos queAudioPlayerreproduzca archivos de audio en otros formatos. Para lograr esta funcionalidad, necesitamos crear una clase adaptadora que implemente laMediaPlayerinterfaz.MediaAdapter, y usarAdvancedMediaPlayerel objeto para reproducir el formato deseado.
AudioPlayerUsando la clase adaptadoraMediaAdapterse pasa el tipo de audio requerido, sin necesidad de conocer la clase real que puede reproducir el formato de audio requerido.AdapterPatternDemoLa clase usaAudioPlayerla clase para reproducir varios formatos.
Paso 1
Crear interfaces para el reproductor de medios y el reproductor de medios avanzado.
MediaPlayer.java
AdvancedMediaPlayer.java
Paso 2
Crear clases de entidad que implementan laAdvancedMediaPlayerinterfaz.
VlcPlayer.java
Mp4Player.java
Paso 3
Crear una clase adaptadora que implementa laMediaPlayerinterfaz.
MediaAdapter.java
Paso 4
Crear una clase de entidad que implementa laMediaPlayerinterfaz.
AudioPlayer.java
Paso 5
Usar AudioPlayer para reproducir diferentes tipos de formatos de audio.
AdapterPatternDemo.java
Paso 6
Ejecutar el programa y mostrar el resultado:
Playing mp3 file. Name: beyond the horizon.mp3 Playing mp4 file. Name: alone.mp4 Playing vlc file. Name: far far away.vlc Invalid media. avi format not supportedOtras extensiones