Repositório: https://github.com/carolrochafloro/DesignPatternsPoC/tree/main/DesignPatternsPoC
Sobre o pattern
O builder pattern permite construir objetos complexos sem a necessidade de criar diversas subclasses herdando da classe principal e sem sobrecarregar o construtor da classe com inúmeros parâmetros, reduzindo a complexidade do código.
Deve ser utilizado quando a construção do objeto precisar ficar separada das partes desse objeto ou quando o processo de construção precisar permitir diferentes representações do mesmo objeto.
Estrutura
Builder interface
Especifica uma interface abstrata para criar partes do produto (objeto).
ConcreteBuilder
Constrói as partes implementando a Builder interface, define a representação do objeto, oferece uma interface para obter o produto.
Director
Chama a Builder interface para construir o objeto.
Product
É o objeto criado pelo builder. Pode incluir classes que definem as partes que o constituem.
Como funciona
O client instancia a classe Director e configura com o Builder referente ao objeto desejado.
A classe Director notifica o builder quando uma parte deve ser construída.
O builder lida com os requests adicionando as partes do produto.
O client obtém o produto do builder.
Vantagens
- Permite variar a representação interna de um objeto: como o objeto é construído através de uma interface genérica, para mudar a representação interna do mesmo só é preciso definir um novo tipo de builder;
- Isola os códigos de construção e representação, melhorando a modularidade do código;
- Oferece maior controle do processo de construção: permite a definição de uma ordem específica para a construção e só permite que o client tenha acesso ao objeto ao final do processo de construção.
Considerações
- A builder interface precisa ser genérica o suficiente para permitir a construção de products para todos os tipos de concrete builders;
- Pode ser preciso acessar partes do produto antes do final da construção, embora não seja o caso na maioria das vezes;
- Na maioria dos casos, os produtos vão ser tão diferentes entre si que não faz sentido criar uma classe abstrata para todos herdarem. O client vai configurar a classe director com o concrete builder necessário.
Como eu fiz
Agora vou descrever o meu passo a passo para criar um builder de personagens de RPG. O tema não foi escolhido por acaso, meu filho é apaixonado por RPG de mesa e a escolha foi pensando nele, que me ajudou com alguns detalhes.
Optei por uma versão stepwise do builder, definindo uma ordem certa para que nenhuma propriedade deixe de ser setada pelo usuário. Para isso, usei interfaces para cada passo, com o método correspondente retornando a interface seguinte. A implementação é bem simples, embora repetitiva.
Criada a classe Character, defini o construtor para receber uma instância de CharacterBuilder e setar as propriedades conforme os valores recebidos no builder.
Criei também as interfaces de cada etapa do processo de criação do personagem, sempre recebendo o parâmetro correspondente e retornando a interface seguinte.
Após criar a entidade e as interfaces, criei o builder implementando todas as interfaces do passo a passo, com as mesmas propriedades da entidade, o construtor privado e o método inicial static, para que só fosse possível iniciar a construção por esse método, que retorna uma instância do próprio construtor.
Por último, implementei todas as interfaces até chegar ao último método em que chamei o construtor do personagem passando a própria classe builder como parâmetro e retornei o mesmo.
Como tive uma experiência recente no trabalho em que precisava construir um objeto complexo para o desenvolvimento de testes de integração, quando estudei essa implementação do builder com os passos definidos achei uma excelente ideia, já que quando existem muitas propriedades é possível que a gente deixe passar alguma e encontre erros mais pra frente.
Referências
Refactoring.guru
Design Patterns: elements of reusable object-oriented software
Top comments (1)
Isso me fez pensar sobre como eu implementaria um Espaço Vetorial genérico, tenho que pensar mais sobre isso e olhar Design Patterns e outras coisinhas pra fazer isso acontecer. Maneiraço, Carol, adorei o texto e os exemplos.