Sobes.tech
Middle

O que é o padrão de projeto 'Construtor' (Builder)?

sobes.tech IA

Resposta da IA

O padrão de design "Builder" (Construtor) é um padrão de criação que fornece uma maneira de criar um objeto complexo passo a passo. Ele separa o processo de construção de um objeto complexo de sua representação, permitindo usar o mesmo processo de construção para criar diferentes representações.

Componentes principais do padrão:

  • Builder: Interface abstrata ou concreta (ou classe) que define um conjunto de métodos para construir passo a passo as partes do produto.
  • ConcreteBuilder: Implementação concreta de Builder que cria uma representação específica do produto. Conhece todos os detalhes da construção.
  • Director: Classe opcional, mas frequentemente usada. Define a ordem na qual os passos de construção são chamados para criar uma configuração específica do produto.
  • Product: Objeto complexo que está sendo construído. Consiste em várias partes.

Vantagens:

  • Permite criar objetos complexos passo a passo, evitando construtores "telescópicos" (construtores com muitos parâmetros).
  • Encapsula a lógica de criação do objeto complexo.
  • Facilita a alteração na representação interna do produto.
  • Permite usar o mesmo processo de construção para criar diferentes variantes do produto.

Aplicabilidade:

  • Quando o processo de criação de um objeto envolve muitas etapas, e essas etapas devem ser realizadas em uma ordem específica.
  • Quando é necessário ter diferentes representações do mesmo objeto.
  • Quando o construtor do objeto possui muitos parâmetros opcionais.

Exemplo:

// Produto
class Pizza {
    private String dough = "";
    private String sauce = "";
    private List<String> toppings = new ArrayList<>();

    public void setDough(String dough) {
        this.dough = dough;
    }

    public void setSauce(String sauce) {
        this.sauce = sauce;
    }

    public void addTopping(String topping) {
        this.toppings.add(topping);
    }

    @Override
    public String toString() {
        return "Pizza com massa: " + dough + ", molho: " + sauce + ", ingredientes: " + toppings;
    }
}

// Interface do construtor
interface PizzaBuilder {
    void buildDough();
    void buildSauce();
    void buildToppings();
    Pizza getPizza();
}

// Construtor concreto
class MargheritaPizzaBuilder implements PizzaBuilder {
    private Pizza pizza = new Pizza();

    @Override
    public void buildDough() {
        pizza.setDough("massa fina");
    }

    @Override
    public void buildSauce() {
        pizza.setSauce("tomate");
    }

    @Override
    public void buildToppings() {
        pizza.addTopping("mozzarella");
        pizza.addTopping("manjericão");
    }

    @Override
    public Pizza getPizza() {
        return this.pizza;
    }
}

// Diretor (opcional)
class Cook {
    private PizzaBuilder pizzaBuilder;

    public void setPizzaBuilder(PizzaBuilder pb) {
        pizzaBuilder = pb;
    }

    public Pizza getPizza() {
        return pizzaBuilder.getPizza();
    }

    public void constructPizza() {
        pizzaBuilder.buildDough();
        pizzaBuilder.buildSauce();
        pizzaBuilder.buildToppings();
    }
}

// Uso
public class BuilderExample {
    public static void main(String[] args) {
        Cook cook = new Cook();
        PizzaBuilder margheritaBuilder = new MargheritaPizzaBuilder();

        cook.setPizzaBuilder(margheritaBuilder);
        cook.constructPizza();

        Pizza margherita = cook.getPizza();
        System.out.println(margherita);
    }
}

No contexto de automação de testes, "Builder" é frequentemente usado para criar dados de teste ou objetos de teste complexos (por exemplo, um objeto usuário com múltiplos atributos, um objeto pedido com várias posições), quando é necessário configurar de forma flexível diferentes variantes desses dados para diferentes cenários de teste.