Patrones Estructurales (VII): Patrón Proxy


Objetivo:

“Proporcionar un sustituto o intermediario para otro objeto de modo que pueda controlarse el acceso que se tiene hacia él”.

Design Patterns: Elements of Reusable Object-Oriented Software

Supongo que todos conocemos el concepto de proxy, al menos en su acepción aplicada a la navegación web. Se trata de una máquina que actúa de intermediaria a la hora de servir páginas web (u otros servicios). En la configuración de área local podemos indicar la IP de esta máquina y será esta máquina la que se conecte a la URL por nosotros y la envíe a nuestro equipo.

De este modo, un equipo no se conectará directamente a la URL, sino que lo hará a través de este intermediario. ¿Por qué hacer esto? Por múltiples motivos: podemos, por ejemplo, restringir las URLs que nuestros clientes (ordenadores de la red local) pueden visitar. O cachear las páginas que se visitan con más frecuencia, haciendo innecesario el acceso a la web “real” en los casos en los que el acceso se repita, proporcionando un ahorro en ancho de banda. En resumen, un proxy será una entidad en la que delegaremos la ejecución de ciertas tareas y que decidirá, en última instancia, qué acciones realizar antes y después de éstas. Los proxies, por tanto, podrían dedicarse perfectamente a la política 🙂

(más…)

Patrones Estructurales (VI): Patrón Composite


Objetivo:

“Componer objetos en árboles para representar jerarquías todo-parte. Composite permite a los clientes tratar objetos individuales y objetos compuestos de una manera uniforme”.

Design Patterns: Elements of Reusable Object-Oriented Software

El patrón Composite se aleja un poco de la línea tradicional de los patrones vistos hasta ahora, ya que rompe uno de los principios de la programación orientada a objetos: una clase, una responsabilidad. En realidad, los más puristas pueden decidir no hacerlo, pero el precio a pagar es demasiado alto para los ingenieros mortales: la simplicidad del modelo.

Cuando diseñamos debemos tener claro que la idea principal es alcanzar un equilibrio entre muchos factores como por ejemplo presupuesto, usabilidad y facilidad para que nuestro código sea reutilizable y pueda ser fácilmente mantenible en un futuro. Si el objetivo del anterior patrón, Flyweight, era el rendimiento, el sine qua non de este patrón es la facilidad de uso.

(más…)

Patrones Estructurales (V): Patrón Flyweight


Objetivo:

“Compartir una parte común del estado de un objeto para hacer más eficiente la gestión de un número elevado de objetos de grano más fino.”

Design Patterns: Elements of Reusable Object-Oriented Software

El patrón Flyweight u “objeto ligero”, a diferencia de algunos de los patrones vistos hasta el momento, no goza de un uso masivo entre la comunidad de ingenieros de software. El motivo no radica en su falta de utilidad o de interés, sino que se centra principalmente en el concepto de rendimiento. A grandes rasgos, se basa en dividir un objeto en dos partes: una parte “común” a un conjunto grande de los objetos de la clase (parte intrínseca), y una parte “privada” que será accesible y modificable únicamente por un objeto en concreto (parte extrínseca).

Un ejemplo simple de Flyweight podría ser el gestor de ventanas del sistema operativo. Un tema de ventanas poseerá atributos como color de fondo, fuente tipográfica, grosor del borde de la ventana, estilo de los botones… Muchos de estos atributos serán comunes a todas las ventanas, por lo que podríamos almacenar toda esta información en un elemento compartido y hacer una llamada a un método para que, haciendo uso de estos atributos comunes y de los parámetros recibidos por el método, se realice una operación que no requiera una instancia exclusiva para ello.

Por ejemplo, realizando una llamada a un método como RenderizarVentana(int x, int y, int ancho, int alto), nuestro objeto Flyweight utilizaría los valores almacenados comunes a todas las ventanas para dibujar una ventana en la posición (x, y) con unas dimensiones (ancho, alto). La instancia de la ventana será única, limitándose a devolver un objeto con las características indicadas. La alternativa simple, como podremos imaginar, sería instanciar un objeto por cada ventana presente en el sistema que almacenara todos estos datos de forma individual más, opcionalmente, valores específicos para la posición y las dimensiones de la ventana. Como siempre ocurre con los patrones de diseño, simplificar una parte del software implicará aumentar la complejidad de otra. En este caso, un diseño más simple se corresponderá con un aumento de consumo de memoria. El límite, nuevamente, se encontrará en el punto de equilibrio que el diseñador estime conveniente.

 

(más…)

Patrones Estructurales (IV): Patrón Bridge


Objetivo:

“Desacoplar una abstracción de su implementación de modo que los dos puedan ser modificados de forma independiente.”

Design Patterns: Elements of Reusable Object-Oriented Software

El patrón Bridge o Puente es normalmente uno de los patrones que más cuesta entender, especialmente si nos ceñimos únicamente a su descripción. La idea tras este patrón, sin embargo, es sencilla: dado que cualquier cambio que se realice sobre una abstracción afectará a todas las clases que la implementan, Bridge propone añadir un nuevo nivel de abstracción entre ambos elementos que permitan que puedan desarrollarse cada uno por su lado.

Si le echamos un ojo al diagrama, es posible que de base no nos aclare demasiado. Nos centraremos en el elemento central: una clase abstracta Abstracción que contiene una referencia a una interfaz Implementor y un método operacion() que no hace más que invocar el método operacionOriginal() de dicha interfaz. Lo que hace esta clase Abstracción es, por tanto, encapsular a la interfaz Implementor exponiendo sus métodos.

(más…)

Patrones Estructurales (III): Patrón Decorator


Objetivo:

“Añadir responsabilidades a un objeto de forma dinámica. Los decoradores proporcionan una alternativa flexible a la herencia para extender funcionalidad.”

Design Patterns: Elements of Reusable Object-Oriented Software

El siguiente de los patrones estructurales que veremos sera el patrón Decorator o decorador. Su filosofía consiste en añadir responsabilidades de forma dinámica con el principal objetivo de evitar la conocida como “explosión de clases”, es decir, la generación de un número elevado de subclases a partir de una superclase común.

Como podemos observar en el gráfico superior, la clase Decorator hereda de la misma clase que el componente que se quiere decorar. Así, cada decorador es capaz de encapsular una instancia de cualquier otro objeto que herede del componente común, bien un componente concreto u otro decorador. Este comportamiento recuerda al que vimos previamente en el patrón Adapter, con la diferencia de que la clase Decorator, a diferencia de la clase Adapter, no transforma una interfaz, sino que añade cierta funcionalidad.

(más…)

Patrones Estructurales (II): Patrón Facade


Objetivo:

“Proporcionar una interfaz unificada a otro conjunto de interfaces de un subsistema. Façade define una interfaz de más alto nivel que hace que el subsistema más fácil de usar.”

Design Patterns: Elements of Reusable Object-Oriented Software

Cuando vimos el patrón Adapter dijimos que el patrón Facade (fachada) estaba muy relacionado con él. Si bien ambos patrones se basan en el mismo principio (encapsular la interfaz de otros elementos), es el motivo y el uso que se le va a dar lo que las diferencia:

  • El patrón Adapterconvierte una interfaz en otra, haciendo que la clase cliente pueda utilizar los métodos de una clase para cuya interfaz no estaba originalmente preparado.
  • El patrón Facade, sin embargo, no realiza ninguna transformación, sino que se limita a simplificar y centralizar un conjunto de invocaciones en un único punto, a la vez que desacopla al cliente del subsistema (siendo la clase Facade la que quedaría acoplada). Es importante tener en cuenta que el patrón Facade no realiza operaciones de transformación, ya que las clases del subsistema, pese a ser envueltas con este elemento, pueden seguir siendo accesibles de forma normal en caso de que fuese necesario, al contrario de lo que ocurre con el patrón Adapter. Un Facade es una forma de simplificar las cosas: es decisión del diseñador si las clases del subsistema son accedidas de forma directa o a través de la fachada.

Resumiendo, Adapter transforma mientras que Facade simplifica y desacopla.

(más…)

Patrones Estructurales (I): Patrón Adapter (Wrapper)


Objetivo:

Convertir la interfaz de una clase en otra interfaz que el cliente espera. Adapter consigue que trabajen juntas clases que de otro modo no podrían.

Design Patterns: Elements of Reusable Object-Oriented Software

El patrón Adapter nos abre el camino hacia el segundo grupo de patrones propuestos por el Gang of Four: los patrones estructurales. Si bien los patrones de creación definían la forma en la que los objetos son instanciados, los patrones estructurales se basan en la forma en la que un conjunto de clases se relacionan entre sí para proporcionar una funcionalidad compleja, proporcionando una estructura para conseguir lograr ese objetivo.

La filosofía de Adapter, al igual que vimos con Prototype, es tan simple como autoexplicativa: establecer una capa intermedia que permita comunicarse a dos clases que de otro modo no podrían hacerlo, realizando una adaptación de la interfaz de la clase que proporciona el servicio a la que la solicita.

(más…)