[Delphi] Design Patterns GoF – Builder

Alô, leitores!
Em continuidade aos artigos sobre Design Patterns, estudaremos o Builder, um padrão de projeto da mesma categoria do Abstract Factory, chamada “criacionais” (ou “de criação”). Recebem este nome por serem padrões que envolvem a criação de objetos em diferentes contextos. Vamos conhecer a proposta deste padrão de projeto?

Introdução

Se pesquisarmos por “Builder Pattern” na internet, encontraremos a seguinte definição:

É um padrão de projeto de software que permite a separação da construção de um objeto complexo da sua representação, de forma que o mesmo processo de construção possa criar diferentes representações.

Ao procuramos mais detalhes, descobriremos ainda que existem quatro elementos neste padrão, chamados de Director, Builder, Concrete Builder e Product.

Analogia

Bom, vocês sabem que um dos maiores objetivos do blog é descomplicar conceitos. Para isso, costumo utilizar analogias para facilitar o entendimento. Este artigo não será diferente. Vou apresentar-lhes um exemplo que já é relativamente clássico com o Builder para esclarecer o papel de cada elemento: uma empresa de fast-food.

Imagine que você esteja em um fast-food e que tenha pedido um lanche ao atendente. Este, por sua vez, repassa o pedido para a cozinha, onde o lanche é produzido. Quando pronto, o lanche é entregue ao atendente e, por fim, a você. Nesse pequeno cenário, observa-se:

  • O atendente é apenas um intermediário entre o cliente e a cozinha;
  • O atendente não conhece como o lanche é feito. Apenas repassa o pedido do cliente;
  • O lanche é feito pelos funcionários da cozinha, enquanto o atendente apenas o espera pronto.

Traduzindo em termos técnicos, é possível ligar estes pontos aos elementos do Builder:

  • O atendente é o Director, que solicita a construção de um objeto (produto);
  • O lanche é o Product, ou seja, o produto resultante da construção;
  • O quadro de funcionários que fazem os lanches é o Builder (Interface);
  • O funcionário que preparou o lanche pedido é o Concrete Builder (objeto).

Dessa forma, podemos simplificar a definição do Builder:

É um padrão de projeto que permite encapsular a lógica de construção de objetos, de modo que diferentes representações possam ser criadas a partir de uma mesma interface.

Por quê encapsular?
O encapsulamento refere-se ao fato do Director (atendente) não conhecer como o produto é fabricado. Apenas aguarda o produto pronto para ser entregue ao cliente.

O que são representações?
Considere que cada representação é um tipo de lanche que o fast-food vende. 🙂

Em palavras gerais, o Builder tecnicamente funciona da seguinte forma: o Director “solicita” um Product para o Concrete Builder. Este é responsável por “construir” o produto – no qual denominamos de “complexo”, pois pode ser constituído de várias partes – e devolver para o Director que, como disse anteriormente, não participa do processo de “construção”.

Exemplo de codificação do Builder

Acredito que o conceito ficará ainda mais claro com um exemplo prático. Neste artigo, codificaremos a emissão de um Relatório de Fornecedores em HTML.

Sabemos que a maioria dos relatórios são divididos em diferentes seções para facilitar a interpretação, certo? O objeto que representa um relatório, portanto, pode ser considerado como “complexo”, pois consiste de várias partes que podem ser condicionadas por regras de negócio. Neste exemplo, simularemos essa complexidade por meio de três passos:

  • Construção do cabeçalho
  • Construção do corpo
  • Construção do rodapé

No entanto, este relatório não será um qualquer. Utilizaremos Bootstrap para deixá-lo com um visual mais agradável e responsivo.

Classe Product

Em primeiro lugar, definiremos a classe Product, que consiste no produto que será “construído”. No nosso caso, será uma página HTML:

O método Adicionar será o mais utilizado dessa classe, já que tem a função de concatenar as tags HTML para montagem da página.

Interface Builder

Em segundo lugar, codificaremos a Interface Builder, que declara a sequência de passos para construir o produto:

Classe Concrete Builder

Em seguida, precisamos de uma implementação concreta da Interface acima. Tal classe, que recebe o nome de Concrete Builder, será responsável por implementar cada passo da construção. No nosso exemplo, preencheremos as tags HTML referente à cada seção da página, fazendo referência aos templates do Bootstrap. Embora o código pareça um pouco extenso, a maior parte resume-se a comandos HTML.

Não tem segredo, não é?

Classe Director

O último elemento, chamado Director, tem apenas a função de receber um Concrete Builder como parâmetro para executar a sequência de passos:

Em ação!

Recapitulando então, pessoal: tudo se inicia pelo Director, que equivale ao atendente na analogia no começo deste artigo. O Director recebe um Concrete Builder como parâmetro para executar a sequência de passos. No final deste processo, recebemos um Product “construído”.

Para testar o padrão de projeto, elaborei um formulário simples, no qual carrega um arquivo de dados chamado “vendors.xml” que acompanha a instalação do RAD Studio.

Formulário de exemplo para demonstrar o Design Pattern Builder

No botão de geração do relatório, atente-se à codificação:

A título de conhecimento, vale destacar que o Concrete Builder não precisa ser liberado da memória, já que foi declarado como Interface e o próprio Delphi se encarrega da liberação por meio de um mecanismo de contagem de referência.

Pois bem, este é o resultado:

Exemplo de relatório gerado em HTML

Conclusão

O propósito do padrão de projeto Builder não limita-se a apenas construir objetos complexos. A sua proposta, além disso, é permitir que diferentes representações (ou seja, diferentes produtos) possam ser construídos com a mesma sequência de passos.

Considere, por exemplo, que seja necessário gerar um relatório em PDF com estes mesmos dados. Teríamos apenas que criar um novo Product e um novo Concrete Builder encarregado de construir o cabeçalho, corpo e rodapé neste formato, provavelmente utilizando o QuickReport, FastReports ou Rave Reports. No formulário, basta indicar o Concrete Builder desejado como parâmetro do Director. O resto ocorre naturalmente. 🙂

Não compreendeu muito bem? Sem problemas! Clique no link a seguir para baixar o exemplo completo deste artigo:

 

Grande abraço, pessoal!


 

André Celestino