Continuemos. Hoy nos toca el patrón Facade (ó "Fachada" en español). Plantearemos un ejemplo "abstracto" el cuál nos servirá de guía para definir formalmente lo que provee el patrón.
Consideramos:
- Cliente
- Fachada
- Subsistema (conjunto de clases, cómo un Subsistema de Persistencia :)
Nos detenemos un momento a pensar en lo siguiente: Consideramos al subsistema como un conjunto de clases "complicado", es decir, con varias tareas u operaciones que realizan (ni hablar si existen subsistemas anidados, o sea, subsistemas dentro de otros subsistemas).
Para el cliente común tener que interactuar directamente con el subsistema sería bastante tedioso. Esperen, para el cliente común, recalco. No quita que el subsistema deba ser lo más general posible, proveer todo lo que crea conveniente, garantizar extensibilidad para el cliente particular (y avanzado) que lo deseara. Pero esto es puntual, la mayoría tiene intereses comunes en lo que respecta a la funcionalidad que provee el subsistema en cuestión. Por ejemplo, poco me interesaría saber qué clases (y qué métodos de esa clase) necesitaría para realizar un cálculo complejo (que probablemente requiera ciertas configuraciones antes de invocar esa clase con ése método), yo, como cliente, me gustaría hacer algo como "calculoAvanzado()" y que alguien (¿Una clase?) hiciera la labor "complicada", que debería desacoplar al cliente con el subsistema subyacente. Despacio, vamos despacio, ya se irá aclarando.
Aquí es donde entra en juego nuestra nueva clase "Facade". La clase "Facade" nos brinda (muy amigablemente) lo que necesitamos, desacoplar al cliente del subsistema subyacente, proveyendo una interfaz genérica para usuarios comunes, haciendo del subsistema complejo un subsistema fácil de utilizar. ¡Qué bueno! Sólo tener que invocar un método con parámetros mínimos, o al menos sólo los necesarios, para que el Facade se encarga del resto, instanciar las clases del Subsistema que necesite, y todo lo demás que el Cliente antes hacía.
Claro, y a esto se le agrega la tremenda potencia que tenemos un único punto de acceso, lo que modifiquemos lo hacemos aquí, garantizando la independencia de los Clientes con el subsistema. Por supuesto, una vez más, esto no quita que un cliente particular (y avanzado) quiera extender o utilizar el subsistema a su manera para operaciones específicas las cuales muchas veces se omiten en la clase "Facade" por cuestión de simplicidad (ya que pocas veces son utilizadas).
Acabamos de mencionar el objetivo el patrón "Facade" más sus ventajas aparejadas. Desventajas, talvez la mayor, hay que saber cuándo utilizar una clase "Facade" y también (y más importante todavía) qué operaciones proveerá el Facade, considerando que tiene que proveer aquellas que son comunes a todos los usuarios, y garantizar cierto grado de simplicidad con un bajo acoplamiento entre el cliente y el subsistema. Entonces no es tan fácil hacer un "buen" Facade. No, no lo es, pero sí que vale la pena, lo vale por el sólo hecho de lo que nos provee. Es tremendamente útil (lo será en nuestro Framework de Persistencia [FWP], ya verán…).
Ya que en este capítulo no vamos a dar un ejemplo particular del Facade (lo dejaremos para nuestro FWP), mostramos una breve estructura de lo que planteamos de manera abstracta:
Tomada de http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/facade.html. La imagen es simplemente excelente. Ilustra el propósito y ventaja del patrón "Facade". En la imagen de la izquierda vemos lo que sería sin el patrón (¡flechas de los Clientes hacia el Subsistema "complejo" por todos lados!), dependencia, complejidad en cuánto con qué clase (y método) interactuaremos. En cambio en la imagen de la derecha todo se reduce a nuestra nueva amiga, la clase "Facade", quién hace de intermediario entre los clientes y el subsistema "complejo", garantizando bajo acoplamiento de clientes al subsistema, y fácil, muy fácil (créanme) interacción de clientes con el subsistema.
Hasta aquí tenemos lo que buscábamos, comprender el patrón Facade a grandes rasgos, si entendieron lo anterior, por más mínimo que sea, es más que suficiente en esta instancia. Lo que sigue lo dejo para aquellos que quedaron con un poco de ganas de saber algo más del patrón Facade.
Algo interesante a remarcar es el tema de implementación del patrón Facade. Si bien es muy sencillo crear una clase "Facade" con la interfaz (métodos) que el cliente invocaría, hay que considerar ciertos puntos:
- A veces puede surgir la necesidad de tener un Facade abstracto y varios Facade concretos (por si hubiera varios subsistemas concretos por ejemplo), con esto garantizaríamos que el cliente se mueva únicamente con el patrón facade (abstracto) y los facade concretos (los cuáles NO son accedidos por los clientes) se encargarán de interactuar con el subsistema concreto correspondiente.
- Otra manera es tener un solo Facade con varios objetos de los diferentes subsistemas concretos.
- Se debería considera, para una buena programación, ver aquellas clases del subsistema que deberían ser privadas (sin posibilidad de ser accedidas por el cliente) y aquellas que sí. Es especialmente útil ya que el cliente común sólo usará aquellas que comúnmente usa (suena redundante, pero así es); las clases que quedaron privadas serán usadas para casos particulares por clientes particulares, quienes quieran extender o ampliar el subsistema.
- Consideremos lo que planteábamos al principio que en general el Facade es un "único punto de accedo" (¿Les suena a algo parecido? ¿Quizá a un patrón visto anteriormente?), sí, no hay muchas opciones. Combinar el patrón "Facade" con el patrón "Singleton" suele ser una tarea muy común y sencilla.
Por aquí, mis amigos/as, dejamos. Sigue un poco tedioso, pero sepan que será de mucha ayuda al momento de meternos de lleno con el FWP. ¡Saludos!.