Vivek Viswanathan
Vivek Viswanathan Staff Engineer at Compass. Passionate about building software that pushes hardware to its limits!!

Design Pattern Series - Builder Pattern

The Problem

Let's assume we are building an Alert Management System to capture & direct all the alerts within an organization. How do we model the Alert domain object? Typically an Alert would have a source - the source of the alert, time - when the alert was generated, destination - who should act on the alert, severity - the severity of the alert.

public class Alert {

    LocalDateTime timeOfAlert;
    String message;
    Severity severity;

    String source;
    String destination;

    public Alert (LocalDateTime timeOfAlert, Sting message, Severity severity, String source, String destination) {
        // set the values
    }
}

After the initial version of the system has been integrated with all apps, we would like to add a new attribute - knowledge base - how to resolve the alert. Now, we could either overload the constructor to have the additional attribute knowledgeBase or have a no-arg public constructor and let the developer fill the attributes. There are two problems associated with this evolution of the domain object:

  • Constructor has too many arguments leading to readability problems
  • Invalid state of the object (A no-arg constructor doesn't guarantee a fully populated object)

What is Builder Pattern?

The builder pattern helps in constructing objects that have a valid state and aids the readability of the code. It also helps in evolution of the software without compromising on the code quality. The builder will contain all the fields of the parent class and would typically have a build method that would provide the populated object. Any validation could be added in the build method to aid in verification. Here is a sample code with the Alert class using builder pattern:

public class Alert {

    public static class Builder {

        LocalDateTime timeOfAlert;
        String message;
        Severity severity;

        String source;
        String destination;
        String knowledgeBase;

        public Builder withSource(String source) {
            this.source = source;
            return this;
        }

        public Builder withDestination(String destination) {
            this.destination = destination;
            return this;
        }

        public Builder atTime(LocalDateTime timeOfAlert) {
            this.timeOfAlert = timeOfAlert;
            return this;
        }

        // similarly named methods for rest of the attributes

        public Alert Build() {
            Alert alert = new Alert();

            alert.source = this.source;
            alert.destination = this.destination;
            alert.knowledgeBase = this.knowledgeBase;

            alert.timeOfAlert = this.timeOfAlert;
            alert.message = this.message;
            alert.severity = this.severity;

            return alert;
        }
    }

    private Alert() {
    }
 
    // All the attributes in Alert Class
}

With the above pattern implemented in our Alert class, let's see how we the Alert object is created:

Alert alert = Alert.Builder()
              .at(today)
              .fromSource("Application-1")
              .toDestinationTeam("L-1 Support")
              .withSeverity(Severity.HIGH)
              .havingMessage("System went down")
              .usingKnowledgeBase("wiki link to restart the system")

The above code is very clean, readable and easily maintainable. Feel free to comments if you have anything to ask or add.

comments powered by Disqus