When constructors aren’t doing it for you, use a Builder
I believe it was around 2016 when I first read the book Effective Java and I was hooked . It also happened to be one of the first programming books I read and I haven’t found one that provide as much value as that one did ever since. In this article I wanted to talk about one technique from the book that I find very useful.
Consider using the builder pattern when you feel the need to create multiple or long constructors. It will simplify your code, increase readability and allow for immutability.
When to use it?
If you need to create an object that has many possible parameters, combinations, and so forth, then this pattern is quite useful. Read on to find out how it works.
Imagine we want to model a tax return statement. Just think about the number of fields we can have here. The straightforward way would be to create a constructor, see below for the example.
So here we have a long constructor and when instantiated would be hard to read and understand which argument corresponds to what value. It’s also problematic if we want to add a new field later on. Or if we want to model different combinations.
There are obviously other ways to do this, perhaps using multiple constructors, or setters, or container objects. But let me show you how this can be done using a builder.
Determine mandatory fields
One thing we can note about this example is that most people will probably just need to specify income from labor and their age. So let’s say that those two fields are mandatory and that the rest are optional. This means that we want labor income and a person's age in the constructor, but the other fields should be specified after.
Now, we don’t want to use setters, why? Because that means that we can have objects that are not yet fully constructed (semantically) which is problematic when it comes to multi-threading for instance. Therefore we want to enforce immutability for our tax return.
Using the Builder pattern
The builder in this case would look something like this.
I have removed some fields for brevity, but keep in mind the problem we are solving here as mentioned above.
What can you note about this example?
- The tax return has only final fields where the optional values have been specified in the builder.
- It is very easy to create any type of combination of complicated tax returns.
- We can also add new fields without breaking current users.
- The tax return cannot be created without using a builder due to having a private constructor.
It also makes the code easy to read since all the special fields now have names.
I considered ending the article here but decided to talk a little bit about another simple yet quite powerful technique.
Static factory method
As previously mentioned, constructors have some disadvantages such as not having names. Using a static factory method we can work around this and make our code even more readable.
Given our assumption that most people only need to report their labor income and age we could use a static factory to help like the following example.
This is very contrived but it is useful because it allows to to essentially name a constructor. It also allows you to have multiple constructors with the same type argument. In other words, the following example won’t compile.
But this will.
We can also return the same instance over and over or perhaps a subclass. I believe they are more flexible compared to constructors, however, they might not be as easy to find in the code due to them being a method so that’s something to think about when naming them.
 Effective Java by Joshua Bloch