Three Reasons Why I Like the Builder Pattern

There are three ways to create new objects in Java programming language:

  1. The telescoping constructor (anti)pattern
  2. The Javabeans pattern
  3. The builder pattern

I prefer the builder pattern over the other two methods.

Why?

Joshua Bloch described the builder pattern and the benefits of using it in Effective Java. He did an excellent job and I will not repeat these benefits in this blog post.

Instead, I will describe three other reasons why I prefer the builder pattern over the telescoping constructor pattern and the Javabeans pattern.

1. It Helps You to Enforce Better Design

Using either the telescoping constructor pattern or the Javabeans pattern means that the properties of the created object must be created before the actual object is created.

This might or might not be a problem.

If the properties of the created object are fetched by using an external service, it is not a problem. However, if the properties are created in the method which creates the "target" object, it is a problem.

In the latter scenario, the lifecycle of the created objects is often bound to the lifecycle of the "target" object.

If this is the case, the builder pattern can help you use the Domain-driven design (DDD) pattern called the aggregate. Martin Fowler specifies the aggregate pattern as follows:

A DDD aggregate is a cluster of domain objects that can be treated as a single unit. An example may be an order and its line-items, these will be separate objects, but it's useful to treat the order (together with its line items) as a single aggregate.

The builder pattern can help you to design your code in a such way that your domain model is divided into aggregates. This means that the all objects belonging to the aggregate are created by the aggregate root object (Order) and can be accessed only via the aggregate root object.

This moves the construction relation to the logic to the place where it belongs.

2. It Makes You Think

Writing code in the traditional way is easy because you don't have to think. All you have to do is write the code which copies information from one place to another. It might take some time to do it, but it isn't a problem to you because you are on your comfort zone.

Maybe you want to just crunch code without thinking what you are doing.

I am not like that (and you shouldn’t be either).

The builder pattern forces you to think about your objects. To be more specific, it forces you to think about the following things:

  • You have to figure out the mandatory and optional properties of an object.
  • You have to identify the properties which lifecycle is bound to the lifecycle of the created object and design the builder so that it emphasizes this.
  • You have to decide what properties cannot be updated after the object is created (and mark these properties as final).
  • You have to decide what properties can be updated and find the best way to update them.

Finding answers to these questions help you to write better code. I can guarantee that if you take the time to find the answers to these questions, your code will look a lot better than the code written on autopilot.

3. It Helps You to Create Domain-specific Languages

If you use create new objects by using the telescoping constructor pattern or the Javabeans pattern, it is hard to add business meaning to your code. You can try to improve the situation by following these principles:

  • The only way you can add business meaning to constructor arguments is to name the arguments in a proper way. This is difficult to do and even if you get it right, the results aren't optimal.
  • If you use setters, you can of course name the setter methods in a way which adds business meaning to them. However, how often have you seen setter methods which are named following this principle?

99 times out of a 100 the created objects are just objects without meaning. They hold data. That is all.

When you use the builder pattern, you can create a domain-specific language (DSL) for creating new objects by naming the methods of your builder class. This helps you to add business meaning to the code which creates new objects.

This raises one question: how can I update the properties of my objects?

You can of course be boring and use setter methods for updating the individual properties of your objects. But you can do something totally different as well.

Instead of updating individual properties, you can group these properties into meaningful groups and update the values of these properties in a single method. If you name this method correctly, you can create a DSL for updating the information of existing objects.

It Is Not a Silver Bullet

Blake Caldwell says that the builder pattern is basically a less error prone alternative for constructors. I agree with him.

The first thing which you notice when you start to use the builder pattern is that the code which creates new objects is easier to write and read. However, after some time you might notice other benefits as well. I know that I did.

However, it is important that you understand that the builder pattern is not a silver bullet.

I think that no one should follow a best practice just because it is a best practice. This applies to the builder pattern as well.

If your object has only a few constructor arguments, it makes no sense to use the builder pattern. However, because of the benefits described in this blog post (and in Effective Java), you should consider using the builder pattern every time when you have to create new objects.

20 comments… add one
  • Edward Beckett Feb 10, 2014 @ 0:03

    I love using the builder pattern. It just fits very well with my conceptualization of constructing objects.

    HouseBuilder.getBuilder().getSlab().get Walls().getRoof().build()

    Readable and Clean

    • Petri Feb 10, 2014 @ 21:37

      I agree with you!

    • Mitch Mar 3, 2014 @ 18:08

      I don't wanna be a pedant, but I would use even more expressive names: :-)

      HouseBuilder.getBuilder().addSlab().addWalls().addRoof().build();

    • Sudipta Dec 16, 2017 @ 0:17

      HouseBuilder.builder().withSlab(Slab).withWalls(List).withRoof(Roof).build()

  • Andre Feb 10, 2014 @ 2:07

    Great post. Using Spring it always bothered me that new entities have be constructed and that the default constructor has to be public. The builder gets around this as one of your previous examples show.

    Answering the questions you mention is not easy though. Sometimes you need to create an entity in more than one step, but would like the benefit of immutability once all fields have been set. At least, like you say, it makes you think.

    • Petri Feb 10, 2014 @ 20:57

      Hi Andre,

      I am happy to hear that you liked this blog post. Also, I agree that the builder pattern has some weaknesses. One of them is that it doesn't work very well with collection properties. You can of course still use it but the code isn't that pretty anymore.

      To be honest, I am not sure which option is a better choice in this situation:

      1. Use the builder pattern even if it results to a "ugly" code.
      2. Create the object by using the builder pattern and set the values of collection properties after the object is created.

      But like you said, the biggest benefit is that it makes you think about these things. In the end, we have to be ready to make compromises (as long as we know what the tradeoff is).

      • Andre Feb 10, 2014 @ 23:57

        One thing I try and use sometimes is Springs BeanUtils implementation. I try as much as possible to match up my DTO's to my entities, and then perform copyProperties. Of course like you say, for collections it means iterating through them and doing the same for each object in the collection.

        No matter what method i use i'm never 100% satisfied though. How we suffer for our craft :-)

        • Petri Feb 11, 2014 @ 0:04

          There are libraries which are specialized in this. These libraries are:

          But as always, they do pretty much the same thing than the Spring BeanUtils implementation. Of course, they have more features but this comes with a cost (increased complexity and "magic").

          • Nick Feb 11, 2014 @ 15:40

            For this purpose I recommend library Orika: Orika

            "It will automatically collect meta-data of your classes to generate mapping objects which can be used together to copy data from one object graph to another, recursively."

            "Orika uses a code generation to produce mappers which are as fast as possible."

          • Petri Feb 11, 2014 @ 20:03

            Hi Nick,

            Thanks for the tip. I will take look at Orika when I have got time to do so.

  • Greg Brown Feb 11, 2014 @ 19:42

    I agree that telescoping constructors are generally not good design practice. However, I don't see Beans as a way to "create" objects, but rather to "configure" them. This is basically the "no-argument" constructor case. All properties have default values, and you set them when you need to change those defaults.

    Builders are similar. You only call the configurator methods for parameters you want to change. You could, for example, call build() directly without invoking any configurator methods. However, a builder is used *only* for construction. So I see a builder as a great way to create a complex immutable object (which could easily be a bean with read-only properties). The builder itself could just as easily be a bean with mutable properties (which is often what I do).

    • Petri Feb 11, 2014 @ 20:43

      Greg,

      that is a good point. I guess it all depends from the context.

      For example, I use setters when I am configuring the application context of a Spring application because most of the beans I need use setters for overriding default values of their properties.

      On the other hand, I use the builder style configuration when I am configuring Spring Security (this was added in 3.2).

      I admit that when I wrote this blog post, I was thinking mostly about domain objects. Like you said, it is important to remember that there are situations when using setters makes sense.

  • Mathias Bogaert Feb 15, 2014 @ 20:02

    Check out https://github.com/analytically/innerbuilder - avoids needing to write/maintain builders manually.

    • Petri Feb 17, 2014 @ 19:21

      That looks really interesting! I will install it immediately. Thanks for the tip!

  • Edward Beckett Feb 21, 2014 @ 4:16

    @Mathias

    Fantastic Work ... Any possibility of porting it to Netbeans? I'm an IDEA fanbois but we use NB at the job...

    Great Job !!!

  • Michael Karneim Jan 16, 2015 @ 7:51

    I wrote an annotation processor called PojoBuilder, which generates the builder during the compile cycle automatically. Just add @GeneratePojoBuilder to you class.
    It works with plain javac, ant, maven, gradle, eclipse, ...
    You can find PojoBuilder at https://github.com/mkarneim/pojobuilder.

    • Petri Jan 16, 2015 @ 23:27

      Thank you for sharing your code generator! I think that it is useful to the readers of this blog post

Leave a Reply