Facade (padrón de deseño)

Os padróns de deseño dan unha solución probada e documentada a problemas que adoitan xurdir no desenvolvemento de software.O padrón de deseño Facade (en galego: Fachada) é un tipo de padrón estrutural.

Propósito editar

O padrón fachada porporciona unha interface unificada de alto nivel para un conxunto de interfaces dun subsistema, facendo que este último sexa mais fácil de usar.

Motivación editar

A principal motivación do padrón fachada é a necesidade de estruturar un sistema en subsistemas menos complexos, minimizando deste modo as comunicacións e as dependencias entre eles.

Aplicabilidade editar

Aplicaremos o padrón fachada cando queiramos:

  • Proporcionar unha interface simple para un subsistema complexo. O padrón fachada pode proporcionar unha vista simple do subsistema que resulta adecuado para a maioría dos clientes. Só aqueles que precisen mais personalización necesitarán ir máis alá da fachada.
  • Desacoplar un sistema dos seus clientes e doutros subsistemas, facendoo mais portable, independente e reutilizable, reducindo as dependencias entre estes.
  • Estruturar varios subsistemas en capas sendo as fachadas o punto de entrada en cada nivel.

Estrutura editar

A estrutura corresponde coa seguinte imaxe:

 

Participantes editar

Fachada (Facade): coñece qué clases do subsistema son responsables ante unha petición, e delega as peticións dos clientes aos obxectos apropiados do subsistema.

Subclases (ModuleA, ModuleB, ModuleC...): implementan a funcionalidade do subsistema. Realizan o traballo solicitado pola fachada. Non coñecen a existencia da fachada.

Colaboracións editar

  • Os clientes comunicanse co subsistema enviando peticións ao obxecto Fachada, o cal reenvía as peticións aos obxectos apropiados.
  • Os clientes que usan a fachada non teñen que acceder directamente ós obxectos do subsistema, aínda que poderían facelo.

Consecuencias editar

As consecuencias máis importantes da aplicación deste padrón son:

  • Redución do acoplamento entre clientes e subsistemas (conseguindo que os cambios das clases do sistema sexan transparentes aos clientes) e o illamento de cambios na implementación.
  • Oculta aos clientes a complexidade do subsistema, facilitando o seu uso sen impedir o acceso ás clases do subsistema no caso no que sexa necesario.
  • Facilita a división en capas e reduce dependencias de compilación.

Vantaxes editar

A principal vantaxa deste padrón consiste en que para modificar as clases dos subsistemas, só hai que realizar cambios na fachada, e os clientes poden permanecer alleos a elo. Ademais, os clientes non necesitan coñecer as clases que hai tras dela.

Inconvenientes editar

Se varios clientes necesitan acceder a subconxuntos diferentes da funcionalidade da que prové o sistema, poderían acabar usando só unha pequena parte da fachada, polo que sería interesante empregar varias fachadas máis específicas en lugar dunha única global.

Padróns relacionados editar

Un dos padróns relacionados co padrón fachada é o Singleton, dado que en determinadas ocasións as fachadas poden ser instancias únicas.

Os GRASP (General Responsibility Assignment Software Patterns) non son padróns de deseño, senón boas prácticas que guían o desenvolvedor para encontrar os padróns de deseño, que son mais concretos. Un dos padróns GRASP é un controlador que actúa como punto de entrada na capa lóxica, o que se pode comparar perfectamente có uso do padrón fachada.

Usos coñecidos (problemas/solucións) editar

Problema: Un cliente necesita acceder a parte da funcionalidade dun sistema mais complexo.

  • Definir unha interface que permita acceder unicamente a esa funcionalidade.

Problema: Existen grupos de tarefas moi frecuentes para as que se pode crear código mais sinxelo e lexible.

  • Definir unha funcionalidade que agrupe estas tarefas en funcións ou métodos sinxelos e claros.

Problema: Unha biblioteca é dificilmente lexible.

  • Crear un intermediario mais lexible.

Problema: Dependencia entre o código do cliente e a parte interna duna biblioteca.

  • Crear un intermediario e realizar chamadas á biblioteca só ou a través del.

Problema: Necesidade de acceder a un conxunto de APIs que poden ademais ter un deseño ineficiente.

  • Crear unha API intermedia, ben deseñada, que permita acceder á funcionalidade das demais.

Problema: Moitas clases cliente queren usar varias clases servidoras, e deben saber cal é exactamente a que lle proporciona cada servizo. O sistema volveríase moi complexo, porque habería que relacionar todas as clases cliente con todas e cada unha das clases servidoras.

  • Crear unha ou varias clases Fachada, que implementen tódolos servizos, de modo que ou tódolos clientes utilicen esa única clase, ou cada grupo de clientes use a fachada que mellor se axuste ás súas necesidades.

Java editar

O seguinte exemplo agocha un calendario cunha API complicada detrás dun padrón Facade más amigable. A saída é:

Data: 2011-05-15
15 días despois: 2011-05-30
import java.util.Calendar;
import java.util.Formatter;
import java.util.GregorianCalendar;
 
/** Fachada */
public class FormatoData {
    private GregorianCalendar gcal;
 
    public FormatoData(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) {  
        FormatoData d = new FormatoData("2011-05-15");   
        System.out.println("Data: "+d);   
        d.sumarDias(15);   
        System.out.println("15 días despois: "+d);
    }
}

Nestoutro exemplo a fachada axuda a acceder comodamente a tódalas funcionalidades dun sistema de préstamo de libros, vídeos e música.

/**
 * O padrón fachada estrutura un entorno de programación e reduce complexidade coa división en subsistemas.
 */

/**
 * Coa interface fachada, temos unha simple interface para acceder a clases diferentes.
 */
public class Fachada {
    private LibrariaLibros libros = new LibrariaLibros();
    private LibrariaVideo videos = new LibrariaVideo();
    private LibrariaMusica musica = new LibrariaMusica();
 
    public void buscarLibros() {
        libros.buscarLibros();
    }

    public void buscarMusica() {
        musica.buscarMusica();
    }

    public void buscarVideo() {
        videos.buscarVideo();
    }
} 
 
public class LibrariaLibros {
 
    public LibrariaLibros() { }
    public void buscarLibros() { /* ... */ }
}
 
public class LibrariaVideo {
   
    public LibrariaVideo() { }
    public void buscarVideo() { /* ... */ }
}
 
public class LibrariaMusica {
 
    public LibrariaMusica() { }
    public void buscarMusica() { /* ... */ }
}

public class Cliente {

    public static void main(String args[]){
        Fachada fachada = new Fachada();
        fachada.buscarLibros();
        fachada.buscarVideo();
        fachada.buscarMusica();
    }
}