Sobes.tech
Middle

Co je to návrhový vzor 'Builder'?

sobes.tech AI

Odpověď od AI

Vzor "Builder" (Stavitel) je návrhový vzor vytváření, který je určen pro krokové sestavování složitých objektů. Odděluje proces sestavování složitého objektu od jeho reprezentace, takže stejný proces sestavování může vytvářet různé reprezentace.

Principy fungování:

  1. Oddělení: Odděluje logiku tvorby objektu od samotného objektu.
  2. Delegace: Klientský kód (Ředitel) deleguje tvorbu objektu samostatné třídě (Builder).
  3. Krokové sestavování: Objekt je sestavován z komponent pomocí sady metod stavitele.

Hlavní účastníci:

  • Product: Složitý objekt, který chceme postavit. Nezávisí na procesu tvorby.
  • Builder: Abstrivní rozhraní, které definuje kroky pro sestavení Product.
  • ConcreteBuilder: Konkrétní implementace Builder, která realizuje kroky sestavení a poskytuje metodu pro získání hotového Product.
  • Ředitel (Volitelný): Určuje pořadí volání kroků sestavení. Není povinný, klientský kód může přímo komunikovat s ConcreteBuilder.

Výhody:

  • Umožňuje vytvářet objekty s velkým množstvím volitelných parametrů čitelnějším způsobem než pomocí konstruktorů s mnoha argumenty nebo řetězců setterů.
  • Umožňuje vytvářet různé variace téhož objektu pomocí stejného procesu sestavení.
  • Skrývá vnitřní strukturu vytvářeného objektu.

Nevýhody:

  • Může zvýšit počet tříd v projektu (Builder, ConcreteBuilder, Product, Ředitel).

Příklad použití: Vytvoření objektu třídy Pizza s různými ingrediencemi.

// 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<>()); // Inicializace seznamu
    }

    @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 nepřidává toppings kromě základních
    }

    @Override
    public Pizza getPizza() {
        return this.pizza;
    }
}
// Ředitel (Volitelný)
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();
        // Může být voláno i jiné metody, například addTopping() v jiném builderu
    }
}

Použití:

// Klientský kód
Kitchen kitchen = new Kitchen();
PizzaBuilder margheritaBuilder = new MargheritaPizzaBuilder();

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

Pizza margherita = kitchen.getPizza();
System.out.println(margherita); // Výstup: Pizza with dough=Thin crust, sauce=Tomato sauce, cheese=Mozzarella, toppings=[]