6 de mayo de 2017

Patrones de diseño - Adaptadores y Envoltorios

Artículo original: Design Patterns - Adapters and Wrappers
http://weblogs.foxite.com/andykramek/archive/2007/01/07/3096.aspx
Autor: Andy Kramek
Traducido por: Ana María Bisbé York


¿Qué es un adaptador y cómo lo utilizo?

El adaptador, como implica su nombre, describe una solución al problema de tener dos interfaces disparejas actuando como un mecanismo de traslación entre ellas.

¿Cómo yo reconozco dónde necesito un adaptador?

La definición formal del adaptador, dada en "Design Patterns, Elements of Reusable Object-Oriented Software" por Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides es:

Convertir la interfaz de una clase en otra interfaz de cliente esperada.

La necesidad de un adaptador generalmente resulta a partir de las modificaciones o mejoramientos de las bibliotecas de clases o componentes COM, Por ejemplo, re-factorizar frecuentemente puede provocar cambios significativos en la forma en que necesita ser definida la interfaz para una clase. Esto a su vez, puede provocar más cambios en el código de la aplicación que llama al servicio de su clase. Hacer los cambios es siempre una opción de alto riesgo que debe ser evitada siempre que sea posible.

Cuando el código fuente está disponible, una solución es mantener los métodos en la interfaz original a la clase; pero eliminar la implementación en los métodos nuevos. Los métodos viejos no hacen más el trabajo real, en su lugar, ellos "controlan" las llamadas a otros métodos. Sin embargo, esto requiere aún, que se modifique el código existente.

La alternativa es crear una clase nueva la cual replique la interfaz esperada y traduzca las llamadas a la interfaz en el formato correcto para reemplazarlo. Al tratar con componentes en los cuales el código no está disponible, es el único método para tratar con los cambios en su interfaz.

¿Cuáles son los componentes de un adaptador?

Un adaptador tiene dos componentes esenciales. Primero, necesitamos una clase que defina la interfaz que tiene que ser adaptada, el "adaptado". Segundo, necesitamos la clase "adaptador" que defina la interfaz esperada y haga corresponder los métodos de la interfaz con aquellos definidos por el adaptador. El cliente llama uno de los métodos "esperados" que están expuesto en un lado del adaptador, el que simplemente pasa la llamada al método apropiado en el adaptado.

¿Cómo implemento un adaptador?

En otras palabras, un adaptador es típicamente implementado utilizando herencia múltiple, al crear una subclase del adaptador que herede los métodos privados y, permitiendo que herede además, la interfaz pública de las clases que definen la interfaz requerida.

Esto presenta problemas en Visual FoxPro, porque no soporta múltiple herencia, que es necesaria para este caso. Una nueva característica que fue introducida en Visual FoxPro 7.0 es la palabra clave IMPLEMENTS que permite que una clase Visual FoxPro, definida por código, herede una interfaz que está definida en un tipo de biblioteca. Sin embargo, debido a que depende del tipo de biblioteca, puede ser utilizada solamente con objetos COM, y no con clases nativas de Visual FoxPro, por lo que realmente no es de mucha ayuda en este caso.

La mejor forma de implementar un adaptador en Visual FoxPro es, crear una clase que exponga los métodos de la interfaz esperada, y que guarde una referencia de objeto al adaptado. Los objetos cliente pueden llamar a sus métodos esperados que a su vez llaman los métodos apropiados del adaptado. El resultado es, que en Visual FoxPro hay una pequeña diferencia entre el adaptador y el decorador, excepto en su objetivo. Un decorador modifica su comportamiento, mientras un adaptador simplemente modifica una interfaz.

Resumen del patrón de adaptador

El patrón adaptador se utiliza para evitar la necesidad de cambiar el código cuando cambia una interfaz, o para permitir futuras modificaciones o implementaciones cuando diseña clases genéricas. Sin embargo, debido a que Visual FoxPro no admite herencia múltiple, el único mecanismo de implementación disponible es idéntico al que utiliza el Decorador.

¿Qué es un envoltorio (wrapper), y cómo lo debo utilizar?

Esta es una buena pregunta, Si estudia "Design Patterns, Elements of Reusable Object-Oriented Software" por Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides verá que no encuentra un patrón llamado "envoltorio" en ningún lado en esta lista de patrones primarios. Sin embargo, con una lectura más profunda de este libro, verá que realmente está enumerada como un sinónimo para los patrones Adaptador y Decorador.

Ahora, esto no tiene mucho sentido para nosotros. Si el patrón "envoltorio" es realmente un sinónimo de ambos, entonces, lógicamente ambos son además, sinónimos entre si y así, los tres términos pueden referirse al mismo patrón - después de todo es un axioma que:

SI a = b Y b = c ENTONCES a = c

¡Y está muy claro que este no es el caso! Como hemos visto, El Decorador y el Adaptador son diferentes en su objetivo, y algunas similitudes en su implementación son irrelevantes en el contexto de definición de patrones (como siempre). Sin la intención de discrepar de los autores del libro, creo, que en este caso, están equivocados.

Nos parece que la palabra "envoltorio" realmente significa cobertura, por tanto describir al decorador o al adaptador como "envoltorios" es también lingüísticamente incorrecto. Ambos patrones confían en engañar al cliente en su comportamiento, haciendo creer que un objeto interpuesto es realmente un origen que tiene que mirar justo como el destino. Ellos pueden, sin embargo, ser mímicos, o impersonales; pero no son realmente envoltorios.

Entonces, ¿dónde puedo utilizar un envoltorio?

Digamos que el objetivo de un envoltorio es controlar el contenido. Como parte de esta función puede; pero no tiene que incluir funciones provistas por ninguno, o ambos, el Decorador o Adaptador. Los envoltorios ofrecen la integración de la funcionalidad que no está definida en objetos sino en un entorno orientado a objetos.

¿Cuáles son los componentes de un envoltorio?

Un envoltorio tiene dos requerimientos esenciales. Primero, necesitamos una implementación que defina la funcionalidad a la que queremos acceder. Esto puede ser un objeto, y puede que no (un ejemplo de una implementación que no es de objeto, podría ser una DLL, a cuyas funciones necesitamos acceder). Segundo, necesitamos una clase "envoltorio" que proporcione una interfaz de objeto para acceder a la implementación y a los métodos que controlan la implementación. El cliente llama a un método con el envoltorio, el que accede la implementación, según sea necesario, para rellenar la petición.

La siguiente definición resume cuáles son las diferencias que hay entre Envoltorios, Decoradores y Adaptadores, que como hemos visto, se implementan utilizando la misma estructura básica:

  • Decorador : Modifica el comportamiento, sin modificar una interfaz existente.
  • Adaptador : Modifica la interfaz sin modificar el comportamiento.
  • Envoltorio : Proporciona la interfaz, y los servicios, su comportamiento se define en cualquier otro lado.

¿Cómo puedo implementar un envoltorio?

Nos parece que la mayoría de las clases que vemos como "administradores" son realmente envoltorios en VFP. Por ejemplo, un administrador de formularios que crea y libera formularios, controla una colección de formularios y que proporciona una interfaz para el acceso al ejecutar formularios es, según nuestra definición anterior, un ejemplo de envoltorio. La distinción de nombre puede ser, porque está tratando con objetos pero que no altera la intención.

Otro ejemplo de un envoltorio podría ser una clase para acceder a funciones de Windows Shell DLLs. Como una clase que incluye métodos para verificar que la DLL requerida está realmente disponible, que sea la versión correcta y que esté registrada correctamente. El envoltorio también es responsable de liberar la DLL de la memoria cuando finaliza con ella.

Resumen del patrón Envoltorio

Un Envoltorio es claramente un patrón en sí mismo, y se diferencia en la intención del Decorador y el Adaptador (los que son fuertes aliados de muchas implementaciones de VFP). Los envoltorios ofrecen a una aplicación, funciones de administración así como acceso a componentes que tienen funcionalidades, como si fueran objetos VFP - aunque sea o no en realidad componentes implementados como un objeto.

No hay comentarios. :

Publicar un comentario