Facade (patrón de diseño)

De Wikipedia, la enciclopedia libre
Saltar a: navegación, búsqueda
Facade UML class diagram.svg

Contenido

[editar] Introducción

Los patrones de diseño dan una solución probada y documentada a problemas de desarrollo de software que aparecen en un contexto similar. El patrón de diseño Fachada (Facade) es un tipo de patrón estructural.

[editar] Propósito

El patrón fachada se utiliza para proporcionar una interfaz unificada de alto nivel para un conjunto de clases en un subsistema, haciéndolo más fácil de usar. Simplifica el acceso a dicho conjunto de clases, ya que el cliente sólo se comunica con ellas a través de una única interfaz.

[editar] Motivación

El patrón fachada viene motivado por la necesidad de estructurar un entorno de programación y reducir su complejidad con la división en subsistemas, minimizando las comunicaciones y dependencias entre éstos.

[editar] Consideraciones para su aplicación

Se aplicará el patrón fachada cuando se necesite proporcionar una interfaz simple para un subsistema complejo, o cuando se quiera estructurar varios subsistemas en capas, ya que las fachadas serían el punto de entrada a cada nivel. Otro escenario proclive para su aplicación surge de la necesidad de desacoplar un sistema de sus clientes y de otros subsistemas, haciéndolo más independiente, portable y reutilizable (esto es, reduciendo dependencias entre los subsistemas y los clientes).

[editar] Estructura

Se puede ver en la figura.

[editar] Participantes

Fachada (Facade): conoce qué clases del subsistema son responsables de una determinada petición, y delega esas peticiones de los clientes a los objetos apropiados del subsistema.

Subclases (ModuleA, ModuleB, ModuleC...): implementan la funcionalidad del subsistema. Realizan el trabajo solicitado por la fachada. No conocen la existencia de la fachada.

[editar] Colaboraciones

Los clientes se comunican con el subsistema a través de la fachada, la cual reenvía las peticiones a los objetos apropiados. Por lo tanto, los clientes que usan esa interfaz no tienen por qué acceder directamente a las subclases del sistema, aunque pueden hacerlo.

[editar] Consecuencias

Las consecuencias más importantes que resultan de la aplicación de este patrón son la reducción del acoplamiento entre clientes y subsistemas (consiguiendo que los cambios de las clases del sistema sean transparentes a los clientes) y el aislamiento de cambios en la implementación. También oculta a los clientes la complejidad del subsistema, facilitando su uso sin impedir el acceso a las clases del subsistema en caso necesario. Además, facilita la división en capas y reduce dependencias de compilación.

[editar] Ventajas e inconvenientes

La principal ventaja del patrón fachada consiste en que para modificar las clases de los subsistemas, sólo hay que realizar cambios en la interfaz/fachada, y los clientes pueden permanecer ajenos a ello. Además, y como se mencionó anteriormente, los clientes no necesitan conocer las clases que hay tras dicha interfaz.

Como inconveniente, si se considera el caso de que varios clientes necesiten acceder a subconjuntos diferentes de la funcionalidad que provee el sistema, podrían acabar usando sólo una pequeña parte de la fachada, por lo que sería conveniente utilizar varias fachadas más específicas en lugar de una única global.

[editar] Patrones relacionados

Uno de los patrones relacionados más directamente es el singleton, dado que en determinadas ocasiones las fachadas pueden ser instancias únicas.

Otros patrones que guardan una cierta relación con el patrón fachada son los GRASP (General Responsibility Assignment Software Patterns), los cuales no son patrones de diseño, sino buenas prácticas que guían al desarrollador para encontrar los patrones de diseño, que son más concretos. Uno de los patrones GRASP es un controlador que actúa como punto de entrada en la capa lógica, lo que se puede comparar perfectamente con el uso del patrón fachada.

[editar] Usos conocidos (Problemas/Soluciones)

Problema: Un cliente necesita acceder a parte de la funcionalidad de un sistema más complejo.

  • Definir una interfaz que permita acceder solamente a esa funcionalidad.

Problema: Existen grupos de tareas muy frecuentes para las que se puede crear código más sencillo y legible.

  • Definir funcionalidad que agrupe estas tareas en funciones o métodos sencillos y claros.

Problema: Una biblioteca es difícilmente legible.

  • Crear un intermediario más legible.

Problema: Dependencia entre el código del cliente y la parte interna de una biblioteca.

  • Crear un intermediario y realizar llamadas a la biblioteca sólo o, sobre todo, a través de él.

Problema: Necesidad de acceder a un conjunto de APIs que pueden además tener un diseño no muy bueno.

  • Crear una API intermedia, bien diseñada, que permita acceder a la funcionalidad de las demás.

Problema: Muchas clases cliente quieren usar varias clases servidoras, y deben saber cuál es exactamente la que le proporciona cada servicio. El sistema se volvería muy complejo, porque habría que relacionar todas las clases cliente con todas y cada una de las clases servidoras.

  • Crear una o varias clases Facade, que implementen todos los servicios, de modo que o todos los clientes utilicen esa única clase, o que cada grupo de clientes use la fachada que mejor se ajuste a sus necesidades.

[editar] Java

El siguiente ejemplo esconde un calendario con un API complicada detrás de un patrón Facade más amigable. La salida es:

Fecha: 2011-05-15
15 días después: 2011-05-30
import java.util.Calendar;
import java.util.Formatter;
import java.util.GregorianCalendar;
 
/** Fachada */
public class FormatoFecha {
    private GregorianCalendar gcal;
 
    public FormatoFecha(String isodate_ymd) {
        String[] a = isodate_ymd.split("-");
        gcal = new GregorianCalendar(Integer.parseInt(a[0]), Integer.parseInt(a[1])-1, Integer.parseInt(a[2]));
    }
 
    public void sumarDias(int dias) { 
        gcal.add(Calendar.DAY_OF_MONTH, dias); 
    }
 
    public String toString() { 
        return String.format("%1$tY-%1$tm-%1$td", gcal);
    }
}
 
/** Cliente */
public class Cliente {
    public static void main(String[] args) {  
        FormatoFecha d = new FormatoFecha("2011-05-15");   
        System.out.println("Fecha: "+d);   
        d.sumarDias(15);   
        System.out.println("15 días después: "+d);
    }
}

En este otro ejemplo la fachada ayuda a acceder cómodamente a todas las funcionalidades de un sistema de préstamo de libros, vídeos y música.

/**
 * El patrón fachada estructura un entorno de programación y reduce complejidad con la división en subsistemas.
 * @author Pperez
 * @version 1.0
 * @author ALC
 * @version 1.1
 */
 
/**
 * Con la interface fachada, tenemos una simple interface para acceder a clases diferentes.
 */
public class Fachada {
    private LibreriaLibros libros = new LibreriaLibros();
    private LibreriaVideo videos = new LibreriaVideo();
    private LibreriaMusica musica = new LibreriaMusica();
 
    public void buscarLibros() {
        libros.buscarLibros();
    }
 
    public void buscarMusica() {
        musica.buscarMusica();
    }
 
    public void buscarVideo() {
        videos.buscarVideo();
    }
} 
 
public class LibreriaLibros {
 
    public LibreriaLibros() { }
    public void buscarLibros() { /* ... */ }
}
 
public class LibreriaVideo {
 
    public LibreriaVideo() { }
    public void buscarVideo() { /* ... */ }
}
 
public class LibreriaMusica {
 
    public LibreriaMusica() { }
    public void buscarMusica() { /* ... */ }
}
 
public class Cliente {
 
    public static void main(String args[]){
        Fachada fachada = new Fachada();
        fachada.buscarLibros();
        fachada.buscarVideo();
        fachada.buscarMusica();
    }
}


[editar] Ejemplos de utilización

En Java las clases java.awt.Graphics y java.awt.Font.

Herramientas personales
Espacios de nombres

Variantes
Acciones
Navegación
Imprimir/exportar
Herramientas
En otros idiomas