Middle
¿Qué es el patrón de diseño 'constructor' (Builder)?
sobes.tech AI
Respuesta de la IA
El patrón "Builder" (Constructor) es un patrón de diseño creacional destinado a crear objetos complejos paso a paso. Separa el proceso de construcción de un objeto complejo de su representación, de modo que el mismo proceso de construcción puede crear diferentes representaciones.
Principios de funcionamiento:
- Separación: Separa la lógica de creación del objeto de este mismo objeto.
- Delegación: El código cliente (Director) delega la creación del objeto a una clase separada (Builder).
- Construcción paso a paso: El objeto se construye a partir de componentes mediante un conjunto de métodos del constructor.
Participantes principales:
- Producto: Objeto complejo que queremos construir. No depende del proceso de creación.
- Builder: Interfaz abstracta que define los pasos para construir el Producto.
- ConcreteBuilder: Implementación concreta de Builder, que realiza los pasos de construcción y proporciona un método para obtener el Producto terminado.
- Director (Opcional): Define el orden en que se llaman los pasos de construcción. No es obligatorio, el código cliente puede interactuar directamente con ConcreteBuilder.
Ventajas:
- Permite crear objetos con muchos parámetros opcionales de manera más legible que usando constructores con múltiples argumentos o cadenas de setters.
- Permite crear diferentes variaciones de un mismo objeto usando el mismo proceso de construcción.
- Oculta la estructura interna del objeto que se está creando.
Desventajas:
- Puede aumentar la cantidad de clases en el proyecto (Builder, ConcreteBuilder, Product, Director).
Ejemplo de uso: Creación de un objeto de la clase Pizza con diferentes ingredientes.
// Producto
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 con masa=" + dough + ", salsa=" + sauce + ", queso=" + cheese + ", ingredientes=" + 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<>()); // Inicialización de la lista
}
@Override
public void buildDough() {
pizza.setDough("Masa fina");
}
@Override
public void buildSauce() {
pizza.setSauce("Salsa de tomate");
}
@Override
public void buildCheese() {
pizza.setCheese("Mozzarella");
}
@Override
public void addTopping(String topping) {
// La Margherita no añade toppings, aparte de los básicos
}
@Override
public Pizza getPizza() {
return this.pizza;
}
}
// Director (Opcional)
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();
// Se pueden llamar a otros métodos, por ejemplo addTopping() en otro builder
}
}
Uso:
// Código cliente
Kitchen kitchen = new Kitchen();
PizzaBuilder margheritaBuilder = new MargheritaPizzaBuilder();
kitchen.setPizzaBuilder(margheritaBuilder);
kitchen.constructPizza();
Pizza margherita = kitchen.getPizza();
System.out.println(margherita); // Salida: Pizza con masa=Masa fina, salsa=Salsa de tomate, queso=Mozzarella, ingredientes=[]