El patrón Builder
Descripción
El objetivo del patrón Builder es abstraer la construcción de objetos complejos de su implementación de modo que un cliente pueda crear objetos complejos sin tener que preocuparse de las diferencias en su implantación.
Ejemplo
Durante la compra de un vehículo, el vendedor crea todo un conjunto de documentos que contienen en especial la solicitud de pedido y la solicitud de matriculación del cliente. Es posible construir estos documentos en formato HTML o en formato PDF según la elección del cliente. En el primer caso, el cliente le provee una instancia de la clase ConstructorDocumentaciónVehículoHtml y, en el segundo caso, una instancia de la clase ConstructorDocumentaciónVehículoPdf. El vendedor realiza a continuación la solicitud de creación de cada documento mediante esta instancia.
De este modo el vendedor genera la documentación con ayuda de los métodos construyeSolicitudPedido y construyeSolicitudMatriculación.
El conjunto de clases del patrón Builder para este ejemplo se detalla en la figura 2-3.1. Esta figura muestra la jerarquía entre las clases ConstructorDocumentaciónVehículo y Documentación. El vendedor puede crear las solicitudes de pedido y las solicitudes de matriculación sin conocer las subclases de ConstructorDocumentaciónVehículo ni las de Documentación.
Las relaciones de dependencia entre el cliente y las subclases de ConstructorDocumentaciónVehículo se explican por el hecho de que el cliente crea una instancia de estas subclases.
La estructura interna de las subclases concretas de Documentación...
Estructura
1. Diagrama de clases
La figura 2-3.2 detalla la estructura genérica del patrón.
Figura 2-3.2 - Estructura del patrón Builder
2. Participantes
Los participantes del patrón son los siguientes:
-
ConstructorAbstracto (ConstructorDocumentaciónVehículo) es la clase que define la firma de los métodos que construyen las distintas partes del producto así como la firma del método que permite obtener el producto, una vez construido.
-
ConstructorConcreto (ConstructorDocumentaciónVehículoHtml y ConstructorDocumentaciónVehículoPdf) es la clase concreta que implementa los métodos del constructor abstracto.
-
Producto (Documentación) es la clase que define el producto. Puede ser abstracta y poseer varias subclases concretas (DocumentaciónHtml y DocumentaciónPdf) en caso de implementaciones diferentes.
-
Director es la clase encargada de construir el producto a partir de la interfaz del constructor abstracto.
3. Colaboraciones
El cliente crea un constructor concreto y un director. El director construye, bajo demanda del cliente, invocando al constructor y reenvía el resultado al cliente.
La figura 2-3.3 ilustra este funcionamiento con un diagrama de secuencia UML.
Figura 2-3.3 - Diagrama de secuencia del patrón Builder
Dominios de uso
El patrón se utiliza en los dominios siguientes:
-
Un cliente necesita construir objetos complejos sin conocer su implementación.
-
Un cliente necesita construir objetos complejos que tienen varias representaciones o implementaciones.
Ejemplo en C#
Presentamos a continuación un ejemplo de uso del patrón escrito en C#. El código C# correspondiente a la clase abstracta Documentacion y sus subclases aparece a continuación. Por motivos de simplicidad, los documentos son cadenas de caracteres para la documentación en formato HTML y PDF. El método imprime muestra las distintas cadenas de caracteres que representan los documentos.
using System;
using System.Collections.Generic;
public abstract class Documentacion
{
protected IList<string> contenido =
new List<string>();
public abstract void agregaDocumento(string documento);
public abstract void imprime();
}
using System;
public class DocumentacionHtml : Documentacion
{
public override void agregaDocumento(string documento)
{
if (document.StartsWith("<HTML>"))
contenido.Add(documento);
}
public override void imprime()
{
Console.WriteLine("Documentación HTML");
foreach (string s in contenido)
Console.WriteLine(s);
}
}
using System;
public class DocumentacionPdf : Documentacion
{
public override void agregaDocumento(string documento)
{
if (documento.StartsWith("<PDF>"))
contenido.Add(documento);
} ...