Middle
Τι είναι το μοτίβο σχεδίασης 'Builder';
sobes.tech AI
Απάντηση από AI
Το μοτίβο "Builder" (Οικοδόμος) είναι ένα δημιουργικό μοτίβο σχεδίασης που προορίζεται για την κατασκευή πολύπλοκων αντικειμένων βήμα προς βήμα. Διαχωρίζει τη διαδικασία κατασκευής ενός πολύπλοκου αντικειμένου από την παρουσίασή του, έτσι ώστε η ίδια διαδικασία κατασκευής να μπορεί να δημιουργεί διαφορετικές παρουσιάσεις.
Αρχές λειτουργίας:
- Διαχωρισμός: Διαχωρίζει τη λογική δημιουργίας του αντικειμένου από το ίδιο το αντικείμενο.
- Ανάθεση: Ο κώδικας πελάτη (Director) αναθέτει τη δημιουργία του αντικειμένου σε μια ξεχωριστή κλάση (Builder).
- Βήμα προς βήμα δημιουργία: Το αντικείμενο συναρμολογείται από συστατικά μέρη με τη βοήθεια μιας σειράς μεθόδων του builder.
Βασικοί συμμετέχοντες:
- Product: Το πολύπλοκο αντικείμενο που θέλουμε να κατασκευάσουμε. Δεν εξαρτάται από τη διαδικασία δημιουργίας.
- Builder: Μια αφηρημένη διεπαφή που ορίζει τα βήματα για την κατασκευή του Product.
- ConcreteBuilder: Μια συγκεκριμένη υλοποίηση του Builder που υλοποιεί τα βήματα κατασκευής και παρέχει μια μέθοδο για την απόκτηση του έτοιμου Product.
- Director (Προαιρετικό): Ορίζει τη σειρά των κλήσεων των βημάτων κατασκευής. Δεν είναι υποχρεωτικό, ο κώδικας πελάτη μπορεί να αλληλεπιδράσει απευθείας με το ConcreteBuilder.
Πλεονεκτήματα:
- Επιτρέπει τη δημιουργία αντικειμένων με μεγάλο αριθμό προαιρετικών παραμέτρων με πιο αναγνώσιμο τρόπο, σε σύγκριση με τη χρήση κατασκευαστών με πολλαπλούς ορίσματα ή αλυσίδες setter.
- Επιτρέπει τη δημιουργία διαφορετικών παραλλαγών του ίδιου αντικειμένου, χρησιμοποιώντας την ίδια διαδικασία κατασκευής.
- Κρύβει τη εσωτερική δομή του δημιουργούμενου αντικειμένου.
Μειονεκτήματα:
- Μπορεί να αυξήσει τον αριθμό των κλάσεων στο έργο (Builder, ConcreteBuilder, Product, Director).
Παράδειγμα χρήσης: Δημιουργία ενός αντικειμένου της κλάσης Pizza με διάφορα συστατικά.
// 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<>()); // Αρχικοποίηση λίστας
}
@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) {
// Η Μαργαρίτα δεν προσθέτει toppings εκτός από τα βασικά
}
@Override
public Pizza getPizza() {
return this.pizza;
}
}
// Director (Προαιρετικό)
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();
// Μπορούν να καλούνται και άλλες μέθοδοι, π.χ. addTopping() σε άλλο builder
}
}
Χρήση:
// Κώδικας πελάτη
Kitchen kitchen = new Kitchen();
PizzaBuilder margheritaBuilder = new MargheritaPizzaBuilder();
kitchen.setPizzaBuilder(margheritaBuilder);
kitchen.constructPizza();
Pizza margherita = kitchen.getPizza();
System.out.println(margherita); // Έξοδος: Pizza with dough=Thin crust, sauce=Tomato sauce, cheese=Mozzarella, toppings=[]