The Builder Design Pattern

Updated on August 6, 2019
JoeFullerWriting profile image

Joe has extensive experience in software engineering, particularly in the Java programming language and AWS technologies.

Source

What Problem Does a Builder Solve?

The builder pattern seeks to solve the issue of oversized constructors when an object has many mandatory instance variables. When this is the case you often have to take time to study the constructor when trying to figure out what parameters go in what order. Additionally if you have sequences of identically typed parameters (e.g four String objects in a row) it can lead to very subtle bugs because the compiler will not complain about the erroneous positioning because all it knows is it has values of the correct type.

Consider the example object below meant to denote a person. When trying to declare a new instance of type Person you need to know the ordering of the names as well as the ordering of the weight and height. Looking at the example declaration you can see it is very difficult to infer which of the two numbers, 80.0 or 73.0, corresponds to the weight or height.

Additionally consider a person with the name "John Joe James", and yes that's the name of someone I knew in high school. With a name like that which is the first name, middle name and last name? It would be extremely hard to infer this from a simple constructor without having to take the extra time to examine the source code for the Person constructor.

Now imagine the example of a class meant to represent the data on a nutritional label for food, you might have to have numeric values for 20 or more nutrients such as protein as well as the calories and other information such as allergy warnings. With that much required information it becomes inevitable that a mistake is going to happen at least once when declaring an instance using a 20 or more parameter constructor, especially when so many are going to be simple numbers.

A bog-standard example of a Java class with six constructor aguments.
A bog-standard example of a Java class with six constructor aguments.
Declaring an instance of the class is painful because you need to remember argument positions. For example, which is height and which is weight?
Declaring an instance of the class is painful because you need to remember argument positions. For example, which is height and which is weight?

One of the common fixes for this problem developers try and use is to declare the Person object using an empty constructor and then call all the setters on the object immediately afterwards. This does solve the issues of having to know the order of the parameters and an example is given below.

This is a bad idea because it means during the chain of setters the object may be in an inconsistent state but can still actually be used. If I accidentally added a call to another method halfway through the list of setters it could have unintended consequences. We want out object to be in a completely valid state when we create it. This also has implications for concurrent code where two or more threads may be operating on a given object, what if thread A required a value to be set that thread B hasn't actually set yet? Failure, that's what.

An example of using an empty constructor followed by setters to make parameter names more explicit.
An example of using an empty constructor followed by setters to make parameter names more explicit.

The builder pattern offers the best of both worlds; giving you a complete object upon return (as long as all the fields are set) as well as preventing you from having to remember the position of different arguments. Let's dive in to an example.

Consider a builder when faced with many constructor parameters.

— Effective Java by Joshua Bloch

Builder Pattern Example

Below you will see the code required to create a builder for the Person object. All the arguments for the sake of this example have been made to be optional however making some arguments mandatory is easy by creating a constructor for the Builder object with the mandatory arguments and having them as parameters for the static builder() method. This exposes a weakness in the builder pattern; it scales well to many optional arguments and does not scale well with mandatory arguments.

You will notice our class declaration for the Person class just got a lot bigger, and now anytime we add a new instance variable to Person (for example adding shoe size) then the builder also needs to be updated. This is another weakness of the builder pattern, it requires boilerplate code and maintenance of the boilerplate. However later in this article I will show you how to turn all that boilerplate into one single annotation that handles maintenance for you.

The Person class extended to follow the builder pattern.
The Person class extended to follow the builder pattern.

As you can see below the builder pattern does allow for much nicer object declarations where every arguments name is explicitly given massively reducing the chances of accidental positioning mistakes leading to hard to find bugs.

Arguably the object declarations are also more pleasing to the eye of the reader, they flow much nicer than long constructors.

This shows of the biggest strength of the builder pattern, it allows explicit parameter setting so the reader never needs to go to the source code of the Person class to examine the constructor. Although you spent some extra time writing the builder implementation it saves countless hours down the line when you don't have to search for subtle bugs caused by swapped parameters.

Declaring a Person instance using the builder is much cleaner, no more guessing what argument goes where.
Declaring a Person instance using the builder is much cleaner, no more guessing what argument goes where.

Advantages of the Builder Pattern

  • No more worrying about what argument goes in what position, the builder pattern is verbose enough to ensure you always know what argument you are working on.
  • Perfect for when an object has a lot of optional arguments.

Disadvantages of the Builder Pattern

  • Doesn't scale well to lot's of mandatory arguments.
  • Lot's of boilerplate code needed for implementation that needs updated anytime the original object is updated.

Reducing the Boilerplate Code

The builder pattern is perfect for making objects with lots of instance variables easier to construct however it does come with quite a lot of boilerplate code. This boilerplate not only makes the object definition more crowded and harder to read through but it also needs to be maintained, if an instance variable is added or removed then the builder also needs to be updated to reflect that change. Wouldn't it be nice if there was a way to remove the boilerplate AND automatically update the builder based on the instance variables? Lombok provides exact that with the @Builder annotation, my introduction to Lombok article covers this and many more of the details.

This has the exact same functionality as the previous builder pattern example, just with no boilerplate code to worry about thanks to Lombok.
This has the exact same functionality as the previous builder pattern example, just with no boilerplate code to worry about thanks to Lombok.

Builder Design Pattern Video Tutorial

Conclusion

Today we looked at how the builder pattern can help reduce the bugs and eye-hurting code associated with oversized constructors. We discussed how although the builder pattern offers great benefit to the object creator it does add work for the object writer in terms of maintaining the builder. Finally I showed you that all the maintenance and boilerplate can be handled by 1 simple Lombok annotation @Builder. Happy coding!

Questions & Answers

    Comments

      0 of 8192 characters used
      Post Comment
      • JoeFullerWriting profile imageAUTHOR

        Joe Fuller 

        3 months ago

        I will also be publishing more similar articles in future, for example about the factory design patter and more Lombok tips

      • JoeFullerWriting profile imageAUTHOR

        Joe Fuller 

        3 months ago

        @Hamza no problem, glad you enjoyed

      • Hamzajaani profile image

        Hamza Hashim 

        3 months ago from Multan

        Thanks for sharing this man,...

      working

      This website uses cookies

      As a user in the EEA, your approval is needed on a few things. To provide a better website experience, owlcation.com uses cookies (and other similar technologies) and may collect, process, and share personal data. Please choose which areas of our service you consent to our doing so.

      For more information on managing or withdrawing consents and how we handle data, visit our Privacy Policy at: https://owlcation.com/privacy-policy#gdpr

      Show Details
      Necessary
      HubPages Device IDThis is used to identify particular browsers or devices when the access the service, and is used for security reasons.
      LoginThis is necessary to sign in to the HubPages Service.
      Google RecaptchaThis is used to prevent bots and spam. (Privacy Policy)
      AkismetThis is used to detect comment spam. (Privacy Policy)
      HubPages Google AnalyticsThis is used to provide data on traffic to our website, all personally identifyable data is anonymized. (Privacy Policy)
      HubPages Traffic PixelThis is used to collect data on traffic to articles and other pages on our site. Unless you are signed in to a HubPages account, all personally identifiable information is anonymized.
      Amazon Web ServicesThis is a cloud services platform that we used to host our service. (Privacy Policy)
      CloudflareThis is a cloud CDN service that we use to efficiently deliver files required for our service to operate such as javascript, cascading style sheets, images, and videos. (Privacy Policy)
      Google Hosted LibrariesJavascript software libraries such as jQuery are loaded at endpoints on the googleapis.com or gstatic.com domains, for performance and efficiency reasons. (Privacy Policy)
      Features
      Google Custom SearchThis is feature allows you to search the site. (Privacy Policy)
      Google MapsSome articles have Google Maps embedded in them. (Privacy Policy)
      Google ChartsThis is used to display charts and graphs on articles and the author center. (Privacy Policy)
      Google AdSense Host APIThis service allows you to sign up for or associate a Google AdSense account with HubPages, so that you can earn money from ads on your articles. No data is shared unless you engage with this feature. (Privacy Policy)
      Google YouTubeSome articles have YouTube videos embedded in them. (Privacy Policy)
      VimeoSome articles have Vimeo videos embedded in them. (Privacy Policy)
      PaypalThis is used for a registered author who enrolls in the HubPages Earnings program and requests to be paid via PayPal. No data is shared with Paypal unless you engage with this feature. (Privacy Policy)
      Facebook LoginYou can use this to streamline signing up for, or signing in to your Hubpages account. No data is shared with Facebook unless you engage with this feature. (Privacy Policy)
      MavenThis supports the Maven widget and search functionality. (Privacy Policy)
      Marketing
      Google AdSenseThis is an ad network. (Privacy Policy)
      Google DoubleClickGoogle provides ad serving technology and runs an ad network. (Privacy Policy)
      Index ExchangeThis is an ad network. (Privacy Policy)
      SovrnThis is an ad network. (Privacy Policy)
      Facebook AdsThis is an ad network. (Privacy Policy)
      Amazon Unified Ad MarketplaceThis is an ad network. (Privacy Policy)
      AppNexusThis is an ad network. (Privacy Policy)
      OpenxThis is an ad network. (Privacy Policy)
      Rubicon ProjectThis is an ad network. (Privacy Policy)
      TripleLiftThis is an ad network. (Privacy Policy)
      Say MediaWe partner with Say Media to deliver ad campaigns on our sites. (Privacy Policy)
      Remarketing PixelsWe may use remarketing pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to advertise the HubPages Service to people that have visited our sites.
      Conversion Tracking PixelsWe may use conversion tracking pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to identify when an advertisement has successfully resulted in the desired action, such as signing up for the HubPages Service or publishing an article on the HubPages Service.
      Statistics
      Author Google AnalyticsThis is used to provide traffic data and reports to the authors of articles on the HubPages Service. (Privacy Policy)
      ComscoreComScore is a media measurement and analytics company providing marketing data and analytics to enterprises, media and advertising agencies, and publishers. Non-consent will result in ComScore only processing obfuscated personal data. (Privacy Policy)
      Amazon Tracking PixelSome articles display amazon products as part of the Amazon Affiliate program, this pixel provides traffic statistics for those products (Privacy Policy)
      ClickscoThis is a data management platform studying reader behavior (Privacy Policy)