El siguiente patrón estructural que vamos a ver es el patrón Facade, que básicamente nos ayuda a crear o nos provee de una interfaz unificada para manejar un conjunto de objetos en un subsistema. De está forma, estaremos definiendo un interfaz de alto nivel que hará los subsistemas más fáciles de manejar. Por hacer una referencia vinculada a la literatura fantástica, sería algo así como “uno para dominarlos a todos” (ESDLA).
La estructuración de un sistema en pequeños subsistemas permite reducir la complejidad de dicho sistema, el problema es que muchas veces crea muchas dependencias entre los subsistemas implementados. Es en este caso donde el patrón Facade nos puede ayudar creando una única interfaz simple que nos permita acceder a las funcionalidades de nuestros subsistemas. De esta forma, los clientes que utilicen nuestro sistema no necesitarán conocer nuestros diferentes subsistemas y su funcionamiento, sino que solo necesitaran conocer el interfaz para manejar el sistema completo.
El patrón Facade se puede aplicar:
- Cuando se quiere proveer de una interfaz simple para un conjunto complejo de subsistemas. Por ejemplo, la aplicación de muchos patrones de diseño provoca la creación de muchas clases muy pequeñas y reutilizables, pero este nivel de granuralidad hace difícil el manejo del sistema, aquí podríamos aplicar este patrón.
- Cuando hay muchas dependencias entre los clientes y el sistema. Aplicando el patrón podemos aumentar el nivel de desacoplamiento aumentando así la independencia y la portabilidad.
- Cuando quieres introducir capas en tus subsistemas, usando el patrón para definir un punto de entrada. Además, si los subsistemas son muy dependientes, podemos simplificar esta dependencia haciendo que estos se comuniquen a través de sus Facades.
Los elementos que componene este patrón son:
- Facade: Conoce los subsistemas implicados en el sistema global, accede a ellos y les envía las peticiones de los clientes.
- Subsystem classes: Implementan la funcionalidad del sistema, realizan las tareas enviadas por el Facade y no tienen referencias a Facade.
Con todo esto, las consecuencias de la aplicación de este patrón son una reducción del número de objetos que tienen que manejar los clientes ya que, en vez de necesitar un objeto por cada subsistema implicado, solo necesitan el objeto Facade. Esto último provoca un acoplamiento más débil entre el sistema y los clientes, con lo cual hace más fácil los cambios o modificaciones en el sistema y sus subsistemas, permitiendonos también menos acoplamiento entre nuestros subsistemas mejorando las dependecias de compilación, cosa muy importante en grandes sistemas. Aunque, la implementación del patrón no impide, en caso de necesitarlo, que algún cliente use o acceda a alguno de nuestros subsistemas.
Pero como siempre, aunque el punto de vista teórico está muy bien y es muy importante, lo mejor es verlo con un pequeño ejemplo para que nos quede del todo claro. En este caso, vamos a coger un sistema simple de dibujo de figuras geométricas.
Subsystem classes:
public class Circle { public void draw() { ... } } public class Square { public void draw() { ... } } public class Rectangle { public void draw() { ... } }
Facade:
public class ShapeProducer() { private Circle circle; private Square square; private Rectangle resctangle; public void drawCircle() { circle = new Circle(); circle.draw(); } public void drawSquare() { square = new Square(); square.draw(); } public void drawRectangle() { rectangle = new Rectangle(); rectangle.draw(); } }
Client:
public class Client { public static void main(String[] args) { ShapeProducer sp = new ShapeProducer(); sp.drawCircle(); sp.drawSquare(); sp.drawRectangle(); } }
Como vemos, si no tuviéramos el objeto Facade, el cliente tendría que conocer y tener definidos los tres objetos de nuestro subsistema, de esta forma, solo necesita nuestro objeto Facade.
Otros patrones realcionados con este son: Abstract Factory, que puede ser utilizado junto con Facade. Mediator, no visto aún, similar a Facade en el aspecto de abstraer funcionalidad, pero realizando otro enfoque. Y está indirectamente relacionado con Singleton, ya que muchas veces el objeto Facade es Singleton también.
Bueno, hasta aquí por hoy. Nos vemos.