Patrones de diseño - Fachada

El patrón Fachada (Facade) proporciona una interfaz unificada y simplificada a un grupo de interfaces de un subsistema. Este patrón pertenece al grupo de patrones estructurales ya que su objetivo es agregar una interfaz al sistema existente para ocultar sus complejidades.

Necesidad

Tenemos un conjunto de objetos que realizan una tarea compleja y para poder llevarla a cabo se necesita inicializar las clases de estos estos objetos, manejar sus dependencias y llamar a sus métodos siguiendo un orden especifico. La mayoría de los clientes no necesitan conocer el funcionamiento interno de estas clases y sus interacciones, y tan solo necesitan conocer el resultado final que proporcionan.

Con el patrón Fachada añadimos una sola clase que proporciona métodos simplificados requeridos por el cliente y delega la instanciación y las llamadas a métodos de las clases complejas. De esta forma permitimos al cliente simplificar el uso de esta funcionalidad, pero no eliminamos la posibilidad de que interaccione con las clases de bajo nivel.

Implementación

En este ejemplo vamos a diseñar un proceso de preparación y envío de documentos que tienen que seguir un método complejo de preparación:

  1. Cuando el documento esta creado tiene que ajustarse siguiendo diferentes análisis para que cumpla una determinada estructura compleja. Esto se realiza con una librería implementada en la clase AjustarDoc
  2. Posteriormente el documento se tiene que completar con diferentes añadidos como cabeceras, pies de páginas, crear índices, modificar fuentes, etc. que se realiza con una librería que implementa la clase CompletarDoc
  3. Por último el documento se tienen que enviar pero antes se tienen que generar una serie de metadatos, crear códigos de verificación y registrar los datos en una DB. Este proceso se implementa en la clase RegistrarDoc

A pesar de que cada una de las librerías permite un número elevado de ajustes, estos son similares en los documentos que procesa el cliente, por lo que se crea una clase PrepararEnvioDoc que va actuar de Fachada de las clases anteriores.

La representación de nuestras clases sería así:

Patrón Fachada

Código en Vala

Primero tenemos las tres clases que realizan las tareas de las librerías para ajustar, completar y registrar el documento:

AjustarDoc.vala
class AjustarDoc : GLib.Object 
{ 
    public AjustarDoc (Documento doc)  
    { 
        // inicaliza la clase  
    } 
     
    public AjustarDoc conAjLexico() 
    { 
        print ("AjustarDoc: Ajustes Léxicos\n"); 
        return this; 
    } 
     
    public AjustarDoc conAjSemantico() 
    { 
        print ("AjustarDoc: Ajustes Semánticos\n"); 
        return this; 
    } 
     
    public AjustarDoc conAjSintactico() 
    { 
        print ("AjustarDoc: Ajustes Sintácticos\n"); 
        return this; 
    } 
} 

CompletarDoc.vala
class CompletarDoc : GLib.Object 
{ 
    public CompletarDoc (Documento doc) 
    { 
        // inicializa la clase 
    } 
     
    public CompletarDoc conCabecera() 
    { 
        print ("CompletarDoc: Cabecera\n"); 
        return this; 
    } 
 
    public CompletarDoc conPiePag() 
    { 
        print ("CompletarDoc: Pie de página\n"); 
        return this; 
    } 
     
    public CompletarDoc conIndice() 
    { 
        print ("CompletarDoc: Generando índice\n"); 
        return this; 
    } 
     
    public CompletarDoc conFuentes() 
    { 
        print ("CompletarDoc: Cambiando fuentes\n"); 
        return this; 
    } 
     
    public CompletarDoc conFirmas() 
    { 
        print ("CompletarDoc: Añadiendo Firmas\n"); 
        return this; 
    } 
     
    public CompletarDoc conThumbnails() 
    { 
        print ("CompletarDoc: Añadiendo thumbnails\n"); 
        return this; 
    }  
     
} 

RegistrarDoc.vala
class RegistrarDoc : GLib.Object 
{ 
    public RegistrarDoc (Documento doc) 
    { 
        // inicializa la clase 
    } 
     
    public RegistrarDoc conMetadatos () 
    { 
        print ("RegistraDoc: Generando metadados\n"); 
        return this; 
    } 
     
    public RegistrarDoc conCComp () 
    { 
        print ("RegistraDoc: Añadiendo código de comprobación\n"); 
        return this; 
    }  
 
    public RegistrarDoc conNRegistro () 
    { 
        print ("RegistraDoc: Número de registro interno\n"); 
        return this; 
    } 
     
    public RegistrarDoc conGuardarDatos () 
    { 
        print ("RegistraDoc: Guardando datos\n"); 
        return this; 
    }  
} 

Para facilitar el uso de estas clases creamos la clase PrepararEnvioDoc que implementa el patrón fachada:

PrepararEnvioDoc.vala
class PrepararEnvioDoc : GLib.Object 
{ 
    private Documento _doc; 
    public AjustarDoc ajustardoc { get; private set; } 
    public CompletarDoc completardoc { get; private set; } 
    public RegistrarDoc registrardoc { get; private set; } 
     
    public PrepararEnvioDoc (Documento doc) 
    { 
        _doc = doc;  
        _ajustardoc = new AjustarDoc (_doc) 
                        .conAjLexico() 
                        .conAjSemantico() 
                        .conAjSintactico();  
        _completardoc = new CompletarDoc (_doc) 
                        .conCabecera() 
                        .conPiePag() 
                        .conIndice() 
                        .conFuentes() 
                        .conThumbnails(); 
        _registrardoc = new RegistrarDoc (_doc) 
                        .conMetadatos() 
                        .conCComp() 
                        .conNRegistro(); 
    } 
}  

En el constructor de esta clase se crean las tres clases AjustarDocCompletarDocRegistrarDoc añadiendo en cada una las opciones que queremos. Para facilitar la creación parametrizada utilizo lo que se denomina interfaz fluido (fluent interface), que permite ir añadiendo métodos encadenados. 

El cliente que utiliza la clase:

UsoPatronFachada.vala
public class UsoPatronFachada : GLib.Object 
{ 
    public static int main (string[] args) 
    { 
        Intl.setlocale (ALL); 
         
        var doc = new Documento("detalle del documento"); 
        var prepdoc = new PrepararEnvioDoc (doc); 
         
        // aunque PrepararEnvioDoc se encarga de todo 
        // también podemos llamar a las clases internas 
        // para modificar algo 
        prepdoc.completardoc.conFirmas(); 
         
        // al final guardamos el documento 
        prepdoc.registrardoc.conGuardarDatos(); 
         
        return 0; 
    } 
} 

Solo con instanciar la clase PrepararEnvioDoc se generan los procesos de las clases internas de forma automática. Pero como vemos también podemos llamar a las clases internas directamente como en prepdoc.completardoc.conFirmas().

Por último la clase Documento que nos sirve de entidad para incrustarla en el constructor de PrepararEnvioDoc.

Documento.vala
class Documento : GLib.Object 
{ 
    public string mydoc { get; private set; } 
         
    public Documento (string mydoc) 
    { 
        this._mydoc = mydoc; 
    } 
} 

Construimos y ejecutamos el programa:

❯ valac AjustarDoc.vala CompletarDoc.vala RegistrarDoc.vala PrepararEnvioDoc.vala Documento.vala UsoPatronFachada.vala -o UsoPatronFachada
❯ ./UsoPatronFachada
AjustarDoc: Ajustes Léxicos
AjustarDoc: Ajustes Semánticos
AjustarDoc: Ajustes Sintácticos
CompletarDoc: Cabecera
CompletarDoc: Pie de página
CompletarDoc: Generando índice
CompletarDoc: Cambiando fuentes
CompletarDoc: Añadiendo thumbnails
RegistraDoc: Generando metadados
RegistraDoc: Añadiendo código de comprobación
RegistraDoc: Número de registro interno
CompletarDoc: Añadiendo Firmas
RegistraDoc: Guardando datos

 

Indice de Patrones

Modificado por última vez enDomingo, 04 Octubre 2020 16:31
(0 votos)
Etiquetado como :

Deja un comentario

Asegúrese de introducir toda la información requerida, indicada por un asterisco (*). No se permite código HTML.