Sobes.tech
Middle

Mi az a tervezési minta 'Builder'?

sobes.tech MI

Válasz az MI-től

A "Builder" (Építő) mintázat egy létrehozó tervezési minta, amely összetett objektumokat lépésről lépésre hoz létre. Elkülöníti egy összetett objektum építési folyamatát a megjelenítésétől, így ugyanaz az építési folyamat különböző megjelenítéseket hozhat létre.

Működési alapelvek:

  1. Elválasztás: Elkülöníti az objektum létrehozásának logikáját magától az objektumtól.
  2. Delegálás: A klienskód (Direktor) az objektum létrehozását egy külön osztályra (Builder) bízza.
  3. Lépésenkénti építés: Az objektum összetevő részekből áll össze a builder módszereinek segítségével.

Fő résztvevők:

  • Product: Az összetett objektum, amit építeni szeretnénk. Nem függ az építési folyamattól.
  • Builder: Egy absztrakt interfész, amely meghatározza a lépéseket a Product építéséhez.
  • ConcreteBuilder: Egy konkrét implementációja a Builder-nek, amely végrehajtja az építési lépéseket és biztosít egy módszert a kész Product lekérésére.
  • Director (Opcionális): Meghatározza az építési lépések hívási sorrendjét. Nem kötelező, a klienskód közvetlenül is kommunikálhat a ConcreteBuilder-rel.

Előnyök:

  • Lehetővé teszi összetett, sok opcionális paraméterrel rendelkező objektumok könnyebb olvashatóságát, mint a sok argumentummal rendelkező konstruktorok vagy láncolt setterek használatával.
  • Lehetővé teszi ugyanazon építési folyamat különböző variációinak létrehozását.
  • Elrejti az épített objektum belső szerkezetét.

Hátrányok:

  • Növelheti az osztályok számát a projektben (Builder, ConcreteBuilder, Product, Director).

Használati példa: Egy Pizza osztály példányának létrehozása különböző összetevőkkel.

// 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<>()); // Toppings lista inicializálása
    }

    @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 nem ad hozzá toppings-t, kivéve az alapokat
    }

    @Override
    public Pizza getPizza() {
        return this.pizza;
    }
}
// Director (Opcionális)
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ás módszerek is hívhatók, például addTopping() más builder esetén
    }
}

Használat:

// Klienskód
Kitchen kitchen = new Kitchen();
PizzaBuilder margheritaBuilder = new MargheritaPizzaBuilder();

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

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