Builder

Origem: Wikipédia, a enciclopédia livre.
Ir para: navegação, pesquisa

Builder é 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.

Estrutura[editar | editar código-fonte]

Diagrama UML da estrutura do padrão Builder

O padrão Builder, da forma como foi descrito no livro Design Patterns: Elements of Reusable Object-Oriented Software, contém os seguintes elementos:

  • director — constrói um objeto utilizando a interface do builder;
  • builder — especifica uma interface para um construtor de partes do objeto-produto;
  • concrete builder — define uma implementação da interface builder, mantém a representação que cria e fornece interface para recuperação do produto;
  • product — o objeto complexo acabado de construir. Inclui classes que definem as partes constituintes.

Utilização[editar | editar código-fonte]

O padrão Builder pode ser utilizado em uma aplicação que converte o formato RTF para uma série de outros formatos e que permite a inclusão de suporte para conversão para outros formatos, sem a alteração do código fonte do leitor de RTF.

A implementação da solução para esse problema pode ser realizada através de uma classe de leitura (director) associada a uma classe capaz de converter o formato RTF para outra representação (builder). O objeto da classe de leitura lê cada token do texto e executa o método apropriado no objeto de conversão, de acordo com tipo do token. A classe de conversão possui um método para cada tipo de token, incluindo os caracteres comuns, parágrafos, fontes e etc. Para cada formato de texto suportado é criada uma classe de conversão especializada (concrete builder). Um conversor para formato ASCII, por exemplo, poderia ignorar qualquer requisição para converter tokens que não fossem caracteres comuns. Um conversor para o formato PDF, por outro lado, iria processar qualquer requisição para poder converter o estilo, além do texto.

Comparação com o Abstract Factory[editar | editar código-fonte]

O padrão Builder é muitas vezes comparado com o padrão Abstract Factory pois ambos podem ser utilizados para a construção de objetos complexos. A principal diferença entre eles é que o Builder constrói objetos complexos passo a passo e o Abstract Factory constrói famílias de objetos, simples ou complexos, de uma só vez.

Exemplo[editar | editar código-fonte]

Neste exemplo, o método lerRTF() (classe LeitorRTF) percorre uma lista com os tokens encontrados no texto de entrada (formato RTF) e, para cada tipo de token, chama um método do objeto de tipo ConversorTexto. Dependendo do formato escolhido para o texto de destino, será escolhida uma implementação da classe ConversorTexto: ConversorPDF, ConversorTeX ou ConversorASCII. Cada uma destas classes implementa os métodos de acordo com as características do formato relacionado. A classe ConversorASCII não implementa os métodos converteParagrafo() e converteFonte() pois este formato (ASCII) não possui elementos de estilo.

Diagrama[editar | editar código-fonte]

Exemplo de Diagrama em UML para o Padrão Builder.

Código[editar | editar código-fonte]

Este código, escrito na linguagem Java, mostra a implementação do diagrama mostrado acima.

 abstract class ConversorTexto {
 	public void converterCaractere(char c) {
 		// vazio
 	}
 
 	public void converterParagrafo() {
 		// vazio
 	}
 
 	public void converterFonte(Fonte f) {
 		// vazio
 	}
 }
 
 class ConversorPDF extends ConversorTexto {
 	public void converterCaractere(char c) {
 		System.out.print("Caractere PDF");
 	}
 
 	public void converterParagrafo() {
 		System.out.print("Parágrafo PDF");
 	}
 
 	public void converterFonte(Fonte f) {
 		System.out.print("Fonte PDF");
 	}
 }
 
 class ConversorTeX extends ConversorTexto {
 	public void converterCaractere(char c) {
 		System.out.print("Caractere Tex");
 	}
 
 	public void converterParagrafo() {
 		System.out.print("Paragrafo Tex");
 	}
 
 	public void converterFonte(Fonte f) {
 		System.out.print("Fonte Tex");
 	}
 }
 
 class ConversorASCII extends ConversorTexto {
 	public void converterCaractere(char c) {
 		System.out.print("Caractere ASCII");
 	}
 }
 
 class LeitorRTF {
 
 	private ConversorTexto conversor;
 
 	LeitorRTF(ConversorTexto c) {
 		this.conversor = c;
 	}
 
 	public void lerRTF() {
 
 		List<Token> tokens = obterTokensDoTexto();
 
 		for (Token t : tokens) {
 			if (t.getTipo() == Token.Tipo.CARACTERE) {
 				conversor.converterCaractere(t.getCaractere());
 			}
 			if (t.getTipo() == Token.Tipo.PARAGRAFO) {
 				conversor.converterParagrafo();
 			}
 			if (t.getTipo() == Token.Tipo.FONTE) {
 				conversor.converterFonte(t.getFonte());
 			}
 		}
 	}
 }
 
 public class Cliente {
 
 	public static void main(String[] args) {
 
 		ConversorTexto conversor;
 		if (args[0].equals("pdf")) {
 			conversor = new ConversorPDF();
 		} else if (args[0].equals("tex")) {
 			conversor = new ConversorTeX();
 		} else {
 			conversor = new ConversorASCII();
 		}
 		LeitorRTF leitor = new LeitorRTF(conversor);
 
 		leitor.lerRTF();
 	}
 }

A classe Cliente determina, através do parâmetro passado ao programa Java ("pdf" para formato PDF, "tex" para Tex e qualquer outro para ASCII), qual das classes derivadas de ConversorTexto irá utilizar na construção da classe LeitorRTF.

Padrões relacionados[editar | editar código-fonte]

Bibliografia[editar | editar código-fonte]