Sobes.tech
Middle

Ce este pattern-ul de proiectare 'Builder'?

sobes.tech AI

Răspuns de la AI

Modelul "Builder" (Constructor) este un pattern de creare, destinat să construiască obiecte complexe pas cu pas. El separă procesul de construcție a unui obiect complex de reprezentarea sa, astfel încât același proces de construcție poate crea diferite reprezentări.

Principii de funcționare:

  1. Separare: Separă logica de creare a obiectului de obiectul în sine.
  2. Delegare: Codul client (Director) delegă crearea obiectului unei clase separate (Builder).
  3. Creare pas cu pas: Obiectul este asamblat din părți componente folosind un set de metode ale builder-ului.

Principalii participanți:

  • Product: Obiectul complex pe care dorim să-l construim. Nu depinde de procesul de creare.
  • Builder: Interfață abstractă, care definește pașii pentru construirea Product.
  • ConcreteBuilder: Implementare concretă a Builder, care realizează pașii de construcție și oferă o metodă pentru obținerea unui Product gata.
  • Director (Opțional): Definește ordinea apelurilor pentru pașii de construcție. Nu este obligatoriu, codul client poate interacționa direct cu ConcreteBuilder.

Avantaje:

  • Permite crearea de obiecte cu un număr mare de parametri opționali într-un mod mai lizibil decât folosirea constructorilor cu mulți parametri sau a lanțurilor de setter.
  • Permite crearea de variații diferite ale aceluiași obiect, folosind același proces de construcție.
  • Ascunde structura internă a obiectului creat.

Dezavantaje:

  • Poate crește numărul de clase în proiect (Builder, ConcreteBuilder, Product, Director).

Exemplu de utilizare: Crearea unui obiect de clasa Pizza cu diferiți ingrediente.

// Product
public class Pizza {
    private String dough;
    private String sauce;
    private String cheese;
    private List<String> toppings;

    public void setDough(String dough) { this.dough = dough; }
    public void setSauce(String sauce) { this.sauce = sauce; }
    public void setCheese(String cheese) { this.cheese = cheese; }
    public void setToppings(List<String> toppings) { this.toppings = toppings; }

    @Override
    public String toString() {
        return "Pizza with dough=" + dough + ", sauce=" + sauce + ", cheese=" + cheese + ", toppings=" + toppings;
    }
}
// Builder
public interface PizzaBuilder {
    void buildDough();
    void buildSauce();
    void buildCheese();
    void addTopping(String topping);
    Pizza getPizza();
}
// ConcreteBuilder
public class MargheritaPizzaBuilder implements PizzaBuilder {
    private Pizza pizza;

    public MargheritaPizzaBuilder() {
        this.pizza = new Pizza();
        this.pizza.setToppings(new ArrayList<>()); // Inițializare listă
    }

    @Override
    public void buildDough() {
        pizza.setDough("Thin crust");
    }

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

    @Override
    public void buildCheese() {
        pizza.setCheese("Mozzarella");
    }

    @Override
    public void addTopping(String topping) {
        // Margherita nu adaugă topping-uri, în afară de cele de bază
    }

    @Override
    public Pizza getPizza() {
        return this.pizza;
    }
}
// Director (Opțional)
public class Kitchen {
    private PizzaBuilder pizzaBuilder;

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

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

    public void constructPizza() {
        pizzaBuilder.buildDough();
        pizzaBuilder.buildSauce();
        pizzaBuilder.buildCheese();
        // Pot fi apelate și alte metode, de exemplu addTopping() în alt builder
    }
}

Utilizare:

// Cod client
Kitchen kitchen = new Kitchen();
PizzaBuilder margheritaBuilder = new MargheritaPizzaBuilder();

kitchen.setPizzaBuilder(margheritaBuilder);
kitchen.constructPizza();

Pizza margherita = kitchen.getPizza();
System.out.println(margherita); // Afișează: Pizza with dough=Thin crust, sauce=Tomato sauce, cheese=Mozzarella, toppings=[]