Search code examples
design-patternsconstructorimmutabilitybuilder

Is there a convention that objects created using the Builder pattern be immutable?


According to the book Design Patterns: Elements of Reusable Object-Oriented Software, Gamma, Helm, Johnson, and Vlissides:

Intent: separate the construction of a complex object from its representation so that the same construction process can create different representations.

In general, the Builder pattern solves the issue with large number of optional parameters and inconsistent state by providing a way to build the object step-by-step and provide a method that will actually return the final object.

With the builder pattern, we have a build method to generate an object which is immutable.

My Question:

Can I use the builder pattern while also keeping setter methods in the class of the generated object, allowing the possibility to mutate the built object?

If I produce mutable objects, should I not use the builder pattern?


Solution

  • There is value in the Builder Pattern than goes beyond just helping to solve the telescoping parameter problem.

    • They can make an API easier to use by clients since the setter methods are self-naming and, therefore, easier to remember.
    • The Builder Pattern enables optional parameters, something that is offered with telescoping constructors only by using potentially awkward overloading.
    • Client code that uses builders can be more self-documenting than code that uses constructors, enabling client code to be easier (and cheaper) to maintain
    • The Builder Pattern can reduce bugs. Large lists of identically typed parameters can be accidentally transposed with telescoping constructors. In such a case, the compiler won't report the error and the resulting bugs can be far removed and hard to track down.
    • Mandatory parameters for objects can be specified in the constructor signature for the Builder. The compiler will insist that these mandatory parameters are always provided at compile time.
    • Useful APIs evolve over time; it is easy to add setter methods to a builder object, while it can be less easy and more error-prone to manage a set of overloaded constructors.
    • The Builder Pattern is concurrency friendly. It is relatively straightforward to keep the mutable builder object thread confined and, therefore, threadsafe.

    Builders are especially useful for constructing immutable objects because, for such objects, all the data must be supplied at build time. When there is a large amount of data to supply or when multiple steps must be completed, the Builder Pattern is pretty easy to recommend.

    There is no rule that builder objects can't build mutable objects, however for mutable objects the JavaBeans pattern provides the same benefits (easy readability, self-documentation, reduced error prone-ness) with less code.