Builder pattern

Intent

Builder is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.

Problem statement

Imagine a complex object that requires laborious, step-by-step initialization of many fields and nested objects. Such initialization code is usually buried inside a monstrous constructor with lots of parameters. Or even worse: scattered all over the client code.

See https://github.com/explorer436/programming-playground/tree/main/java-playground/design-pattern-samples/design-pattern-examples/src/main/java/com/my/company/builderpattern/example1

  1. At the beginning, as the number of fields in the class is very small, we can get away with a constructor that accepts values for all those fields.

    1. See Lec01WithoutBuilderPattern1
  2. As the number of fields in the class keeps increasing, we have to add more and more constructors to accommodate building the class with fields.

    1. See Lec01WithoutBuilderPattern2
    2. See Lec01WithoutBuilderPattern3
  3. We can also try chaining constructors

    1. See Lec01WithoutBuilderPattern3_ChainingConstructors
  4. But as the number of fields increase, there comes a point where using constructors is not an option anymore.

    1. See Lec01WithoutBuilderPattern4
  5. This is where BuilderPattern comes to the rescue.

    Builder separates the construction of a complex object from its representation so that the same construction process can create different representations.

  6. See Lec02WithBuilderPattern1_old_school_way

    1. Advantages with this approach
      1. Writing the builder for the model class is much more easy.
      2. Building the object becomes much more easy.
    2. Disadvantages with this approach
      1. The individual methods in the builder are noisy and are difficult and cumbersome to read and maintain.
      2. Involves manual changes to the builder of any class when the fields in it change.
      3. A little tedious.
  7. We can rewrite this using java.util.function.Consumer

    1. See See Lec02WithBuilderPattern2_advanced_way
    2. In the builder class, replace all the individual methods with one single method that accepts a Consumer of the builder class.
    3. Advantages with this approach
      1. If the fields in the class change, the number of changes to the model and the builder classes are minimal.

      2. We can also do the chaining of with method.

      3. Building the object becomes much more clean.

        All the assignment statements are nicely encapsulated in a lambda expression or a chain (or) lambda expressions if the class has inner objects)

        e.g.

        Person person1 = new PersonBuilder()
               .with(pb -> {
                   pb.salutation = "Mr.";
                   pb.firstName = "John";
                   pb.lastName = "Doe";
                   pb.isFemale = false;
                   pb.address = new AddressBuilder()
                           .with(ab -> {
                               ab.addressLine1 = "123 main st";
                               ab.city = "Phonenix";
                               ab.state = "AZ";
                           })
                           .build();
               })
               .with(pb -> pb.isHomeOwner = true)
               .build();
        
      4. The advanced way of creating builders could save developers a lot of time and trouble. It can also be used to generate a test data for huge complex objects.

Advantages of the Builder pattern

The whole purpose of builder, making object construction easy and readable.

  1. The builder pattern solves the complex Telescopic constructors
  2. Make it easy to create objects that have many attributes.

Use of Builder design pattern in Java core

  1. All the latest libraries (kafka, opensearch, etc.) are using BuilderPattern for objects.
  2. StringBuilder
    1. If you create a StringBuilder object, you can append strings one by one to the same StringBuilder object.
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.append("Java").append("Foundation");
      
  3. StringBuffer
  4. JsonObjectBuilder
  5. Calendar in Java 8
  6. Locale in Java 7
  7. Stream API in Java 8

Reading material

https://github.com/explorer436/programming-playground/tree/main/java-playground/design-pattern-samples/design-pattern-examples/src/main/java/com/my/company/builderpattern

  1. https://www.javastackflow.com/2020/05/builder-design-pattern.html

    TODO

  2. How to use the Builder design pattern with Spring Boot: https://www.javastackflow.com/2022/09/how-to-use-builder-design-pattern-with.html

Lombok’s builder annotation

It is a great way to implement builder pattern


Links to this note