Skip to content

Staged Builders

[..] often referred to as a wizard for building objects.

Another pattern that I like to use a lot is Staged Builder. The traditional implementation of the Builder pattern is usually not very safe against misuse.

It’s a pattern that helps with Compile time > runtime because it shifts validation from runtime to compile time.

Let’s say there is a builder that produces a User.

final var user = new UserBuilder()
    // misses first name, which is required
    .withLastname("..")
    .build()

The API of UserBuilder doesn’t guide you how to properly use it.

The staged builder pattern introduces a proper interface, multiple in fact, without the need to change the builder implementation itself. Apart from the fact that it should be package private then.

interface FirstNameStage {
    LastNameStage withFirstName(String firstName);
}

interface LastNameStage {
    BuildStage withLastName(String lastName);
}

interface BuildStage {
    User build();
}

See also Riptide: HttpBuilder which includes an example of mutually exclusive paths.

References


Last update: September 4, 2021