Design Patterns Catalog

Simplificando o que não é complicado

Builder

O design pattern Builder trata do processo de conversão de uma informação em um estado bruto (exemplos: um arquivo XML ou um arquivo RTF) em um novo objeto estruturado capaz de representar essa informação em um novo formato.

Este pattern se preocupa em separar o processo de interpretação da informação no estado bruto, do processo de construção do objeto estruturado, de forma que um único processo de interpretação possa ser utilizado para gerar diferentes tipos de objetos estruturados.

Vamos trazer esse pattern a um plano concreto, imaginando um programa que faz a conversão de um arquivo XML em um arquivo texto.

Para implementar esse programa utilizando o design pattern Builder, o nosso sistema a partir de uma classe Client (a classe que utiliza o mecanismo implementado pelo Builder) instancia em um primeiro passo um objeto concreto TextBuilder que extende uma classe abstrata Builder. Este TextBuilder tem a função de construir um objeto estruturado que representa um arquivo texto, o TextProduct, a partir da tradução do XML. Um parêntese para melhor compreensão: imagine que quiséssemos construir um PDF a partir de um XML; nesse caso precisaríamos implementar um PDFBuilder que retornaria um objeto PDFProduct.

Design Pattern Builder - Diagrama de Classes

No segundo passo o Client cria um objeto Director passando como parâmetro para o construtor desse Director o objeto TextBuilder (nota: se estivéssemos gerando um PDF passaríamos o PDFBuilder como parâmetro). A responsabilidade desse Director é relizar o parsing da informação no estado bruto e notificar o Builder sobre cada nova informação encontrada no XML através dos métodos implementados pelo Builder (exemplo: textFound(), newParagraphFound()).

O processo de conversão inicia quando o Client invoca o método buildProduct() do Director. Para cada token do XML encontrado pelo Director, será invocado um método correspondente do TextBuilder que receberá a informação encontrada e guardará da forma adequada no TextProduct. O TextBuilder poderá receber notificações de tokens irrelevantes no seu contexto e nesses casos ele irá executar os métodos vazios implementados na sua classe pai, o Builder (por exemplo, se na tradução do XML esperamos que ao encontrar um determinado token o texto convertido apareça em vermelho, o TextBuilder irá ignorar o comando de formatação enquando um PDFBuilder ou um HTMLBuilder irão levar isso em consideração).

Design Pattern Builder - Diagrama de Sequencia

Alguns pontos importantes a serem notados:

  • As classes Builder extendem uma classe abstrata Builder, com métodos responsáveis por receber as notificações de um Director. Essa estratégia é adotada no lugar de uso de uma interface pois podemos fornecer uma implementação vazia para todos os métodos que recebem as notificações, uma vez que nem todo Builder concreto precisa entender todos os tipos de notificação (no exemplo do TextBuilder uma notificação que tenha a ver com a formatação do texto pode ser ignorada)
  • O Builder nos dá os métodos para receber as notificações, mas não um método para recuperar o produto gerado, assim como não existe uma classe pai ou interface para os diferentes produtos gerados. Isso se dá pois os produtos podem ser completamente diferentes, servindo a propósitos distintos. Não faz sentido, então, implementar as diferentes classes que representam os produtos sob uma mesma hierarquia.