Skip to the content.

Builder

The problem

An Order needs a customer and at least one book, plus a handful of optional extras: a gift message, delivery instructions, a promo code, express delivery. Modelling that with constructors forces either one giant constructor full of nulls at every call site, or a “telescoping” pile of overloads that grows combinatorially. Setters would fix readability but make the order mutable and allow half-initialised objects.

The pattern

A Builder collects the fields step by step with a fluent, self-describing API, validates once in build(), and produces an immutable Order:

Order order = Order.forCustomer(alice)
        .add(refactoring)
        .add(effectiveJava)
        .giftMessage("Happy birthday!")
        .express()
        .build();

Benefits

Seen in the wild

StringBuilder, java.net.http.HttpRequest.newBuilder(), Stream.builder(), Lombok’s @Builder, protobuf message builders.

Implementation

Order – the immutable product, with its fluent Builder as a nested class.

Example test

OrderBuilderTest