Sobes.tech
Middle

Czym jest builder (budowniczy) w kontekście rozwoju oprogramowania?

sobes.tech AI

Odpowiedź od AI

Wzorzec projektowy, który oddziela konstruowanie złożonego obiektu od jego reprezentacji, umożliwiając tworzenie różnych reprezentacji tego samego procesu budowy.

Kluczowe cechy:

  • Oddzielenie odpowiedzialności: Logika tworzenia obiektu (etapy konstruowania) i reprezentacja obiektu (produkt końcowy) są oddzielone.
  • Budowa krok po kroku: Obiekt jest budowany krok po kroku, co czyni proces bardziej elastycznym i zrozumiałym.
  • Różne reprezentacje: Ten sam proces konstruowania może być używany do tworzenia różnych wariantów obiektu.
  • Enkapsulacja: Szczegóły tworzenia obiektu są ukryte przed klientem, co upraszcza jego użycie.

Główni uczestnicy:

  • Builder (Budowniczy): Abstrakcyjny interfejs lub klasa definiująca kroki do tworzenia części produktu.
  • ConcreteBuilder (Konkretna Budowniczy): Konkretna implementacja Budowniczego, wykonująca faktyczne konstruowanie części produktu i przechowująca wynik.
  • Director (Reżyser): Klasa, która używa obiektu ConcreteBuilder do konstruowania produktu, wywołując odpowiednie metody w określonej kolejności.
  • Product (Produkt): Złożony obiekt, który jest konstruowany.

Przykład użycia:

Tworzenie obiektu Pizza z różnymi składnikami:

// 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 z ciastem: " + dough + ", sos: " + sauce + ", ser: " + cheese + ", dodatki: " + toppings;
    }
}

// Interfejs budowniczego
interface PizzaBuilder {
    void buildDough();
    void buildSauce();
    void buildCheese();
    void addTopping(String topping);
    Pizza getResult();
}

// Konkretna budowniczy
class MargheritaPizzaBuilder implements PizzaBuilder {
    private Pizza pizza;

    public MargheritaPizzaBuilder() {
        this.pizza = new Pizza();
    }

    @Override
    public void buildDough() {
        pizza.setDough("Cienkie ciasto");
    }

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

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

    @Override
    public void addTopping(String topping) {
        // Margherita nie ma dodatkowych składników domyślnie
    }

    @Override
    public Pizza getResult() {
        return pizza;
    }
}

// Reżyser
class Cook {
    private PizzaBuilder pizzaBuilder;

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

    public void constructPizza() {
        pizzaBuilder.buildDough();
        pizzaBuilder.buildSauce();
        pizzaBuilder.buildCheese();
        // Dodatkowe składniki mogą być dodane tutaj w zależności od typu pizzy lub wymagań
    }
}

// Kod klienta
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);
    }
}

Zastosowanie gdy:

  • Konieczne jest tworzenie złożonego obiektu z wieloma opcjonalnymi parametrami.
  • Proces tworzenia obiektu jest sekwencyjny i obejmuje wiele kroków.
  • Należy tworzyć różne warianty tego samego obiektu, używając tego samego algorytmu konstruowania.
  • Chcemy uniknąć konstruktora z dużą liczbą parametrów ("telescoping constructor").

Zalety:

  • Poprawia czytelność i utrzymanie kodu.
  • Zapewnia elastyczność w tworzeniu obiektów.
  • Umożliwia tworzenie obiektów niemutowwalnych.
  • Eliminuję potrzebę wielu konstruktorów.

Wady:

  • Może zwiększyć liczbę klas w projekcie (dla każdego typu obiektu i każdego budowniczego).
  • Wymaga początkowego wysiłku projektowego.