Middle
Co je to builder v kontextu vývoje softwaru?
sobes.tech AI
Odpověď od AI
Vzor návrhu, který odděluje konstrukci složitého objektu od jeho prezentace, umožňuje vytvářet různé prezentace téhož konstrukčního procesu.
Klíčové vlastnosti:
- Oddělení odpovědností: Logika tvorby objektu (kroky konstrukce) a prezentace objektu (výsledný produkt) jsou oddělené.
- Krok za krokem konstrukce: Objekt je stavěn krok za krokem, což činí proces flexibilnějším a srozumitelnějším.
- Různé prezentace: Stejný konstrukční proces může být použit pro tvorbu různých variant objektu.
- Zapouzdření: Detaily tvorby objektu jsou skryty před klientem, což usnadňuje jeho použití.
Hlavní účastníci:
- Builder (Stavitel): Abstrétní rozhraní nebo třída, která definuje kroky pro tvorbu částí produktu.
- ConcreteBuilder (Konkrétní stavitel): Konkrétní implementace stavitele, která skutečně sestavuje části produktu a uchovává výsledek.
- Director (Ředitel): Třída, která používá objekt ConcreteBuilder k sestavení produktu, voláním odpovídajících metod v určité sekvenci.
- Product (Produkt): Složitý objekt, který je sestavován.
Příklad použití:
Vytvoření objektu Pizza s různými ingrediencemi:
// Produkt
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 addTopping(String topping) {
if (toppings == null) {
toppings = new ArrayList<>();
}
toppings.add(topping);
}
@Override
public String toString() {
return "Pizza s těstem: " + dough + ", omáčkou: " + sauce + ", sýrem: " + cheese + ", toppings: " + toppings;
}
}
// Rozhraní Builder
interface PizzaBuilder {
void buildDough();
void buildSauce();
void buildCheese();
void addTopping(String topping);
Pizza getResult();
}
// Konkrétní Builder
class MargheritaPizzaBuilder implements PizzaBuilder {
private Pizza pizza;
public MargheritaPizzaBuilder() {
this.pizza = new Pizza();
}
@Override
public void buildDough() {
pizza.setDough("Tenčí těsto");
}
@Override
public void buildSauce() {
pizza.setSauce("Rajčatová omáčka");
}
@Override
public void buildCheese() {
pizza.setCheese("Mozzarella");
}
@Override
public void addTopping(String topping) {
// Margherita nemá žádné další toppings ve výchozím nastavení
}
@Override
public Pizza getResult() {
return pizza;
}
}
// Ředitel
class Cook {
private PizzaBuilder pizzaBuilder;
public void setPizzaBuilder(PizzaBuilder pb) {
pizzaBuilder = pb;
}
public void constructPizza() {
pizzaBuilder.buildDough();
pizzaBuilder.buildSauce();
pizzaBuilder.buildCheese();
// Další toppings lze přidat zde na základě typu nebo požadavků na pizzu
}
}
// Klientský kód
public class PizzaShop {
public static void main(String[] args) {
Cook cook = new Cook();
PizzaBuilder margheritaBuilder = new MargheritaPizzaBuilder();
cook.setPizzaBuilder(margheritaBuilder);
cook.constructPizza();
Pizza pizza = margheritaBuilder.getResult();
System.out.println(pizza);
}
}
Používá se, když:
- Je potřeba vytvořit složitý objekt s mnoha volitelnými parametry.
- Proces tvorby je sekvenční a zahrnuje více kroků.
- Je třeba vytvořit různé varianty téhož objektu pomocí stejného konstrukčního algoritmu.
- Je třeba se vyhnout konstruktoru s velkým počtem parametrů ("telescoping constructor").
Výhody:
- Zlepšuje čitelnost a udržovatelnost kódu.
- Poskytuje flexibilitu při vytváření objektů.
- Umožňuje vytváření neměnných (immutable) objektů.
- Odstraňuje potřebu velkého množství konstruktorů.
Nevýhody:
- Může zvýšit počet tříd v projektu (pro každý typ objektu a každého stavitele).
- Vyžaduje počáteční návrhové úsilí.