Saltar al contenido

Builder

Un patrón creacional para armar un objeto complejo paso a paso, con el proceso de construcción separado del resultado.

7 min. de lectura

Builder es un patrón creacional que permite construir objetos complejos paso a paso, separando el proceso de construcción de la representación final.

El problema

Un Order en AndesShop puede tener: uno o más productos, un método de envío, un cupón de descuento opcional, envoltorio para regalo opcional, un seguro de envío opcional, y una nota para el destinatario opcional. Un constructor que cubra todas las combinaciones termina así:

new Order(items, shippingMethod, null, true, false, null);

Nadie puede leer esa línea y saber qué es cada null o cada boolean sin ir a mirar la firma del constructor. Y si mañana se agrega un campo nuevo, hay que agregar un parámetro más a una lista que ya es demasiado larga — o multiplicar constructores sobrecargados para cada combinación relevante.

La solución

Builder extrae la lógica de construcción a un objeto aparte, que arma el resultado paso a paso a través de métodos con nombre propio, y lo entrega recién al final con un método build(). Cada llamada es legible por sí sola, y los pasos opcionales simplemente no se llaman.

Estructura de Builder: el builder acumula partes y produce un Order ya válido, que es dueño de sus items.

Ejemplo en Java

class Order {
    private final List<Item> items;
    private final ShippingMethod shippingMethod;
    private final boolean giftWrap;
    private final String couponCode;

    // Constructor privado: solo el Builder puede crear un Order
    private Order(OrderBuilder builder) {
        this.items = builder.items;
        this.shippingMethod = builder.shippingMethod;
        this.giftWrap = builder.giftWrap;
        this.couponCode = builder.couponCode;
    }

    static class OrderBuilder {
        private final List<Item> items = new ArrayList<>();
        private ShippingMethod shippingMethod = ShippingMethod.STANDARD;
        private boolean giftWrap = false;
        private String couponCode;

        public OrderBuilder addItem(Item item) {
            items.add(item);
            return this;
        }

        public OrderBuilder withShippingMethod(ShippingMethod method) {
            this.shippingMethod = method;
            return this;
        }

        public OrderBuilder withGiftWrap() {
            this.giftWrap = true;
            return this;
        }

        public OrderBuilder withCoupon(String code) {
            this.couponCode = code;
            return this;
        }

        public Order build() {
            if (items.isEmpty()) {
                throw new IllegalStateException("An order needs at least one item");
            }
            return new Order(this);
        }
    }
}
// Client code: cada línea explica qué está configurando
Order order = new Order.OrderBuilder()
    .addItem(jacket)
    .addItem(hikingBoots)
    .withShippingMethod(ShippingMethod.EXPRESS)
    .withGiftWrap()
    .build();

Cuándo usarlo

  • Cuando construir un objeto requiere varios pasos, muchos de ellos opcionales, y un constructor tradicional se volvería ilegible.
  • Cuando querés poder construir distintas representaciones del mismo objeto reutilizando gran parte del mismo proceso.

Cuándo evitarlo

Para objetos simples con dos o tres campos obligatorios, un constructor normal (o un named constructor / factory estático) es más directo y no necesita una clase extra.

Ventajas y desventajas

VentajasDesventajas
Permite construir objetos paso a paso, e ir postergando pasos opcionalesAgrega una clase adicional (el Builder) por cada objeto complejo
El código de construcción queda legible, cada paso tiene nombre propioPuede quedar sobredimensionado para objetos con pocos campos
Facilita reutilizar el mismo proceso de construcción para variantes distintas del objeto

Relación con otros patrones

  • Se puede combinar con Abstract Factory: la fábrica decide qué builder usar según la familia de producto.
  • A diferencia de Prototype, que crea objetos copiando uno existente, Builder los construye desde cero, pieza por pieza.

Te sirvió, compartilo

// ¿te sirvió?
// compartilo