Saltar ao contido

Facade (padrón de deseño)

Na Galipedia, a Wikipedia en galego.

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 | editar a fonte]

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 | editar a fonte]

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 | editar a fonte]

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 | editar a fonte]

A estrutura corresponde coa seguinte imaxe:

Participantes

[editar | editar a fonte]

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 | editar a fonte]
  • 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 | editar a fonte]

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.

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 | editar a fonte]

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 | editar a fonte]

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 | editar a fonte]

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.

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();
    }
}