How difficult can it ever be to build a list of objects in Java and Kotlin using the builder pattern?

Hello everyone! Some days ago I had to build a list of objects and I would like to use the Builder pattern.

You don’t bother about Java? Skip to Kotlin!

In this example, I will image that I will build an automobile manufacturers list, so I will have a classic Manufacturer builder that I can use like:

I have a builder and obviously my Manufacturer object is immutable!

I need a list of manufacturers and I wouldn’t write verbose code like:

After some refactoring and tests, I finally decide to have a ManufacturerListBuilder with an add method that accepts in input a Function<UserFilterBuilder, UserFilterBuilder>, so I can provide a builder every time I need to add an element using my builder, let’s look to the usage:

As you can see the code looks more compact and the list build responsibility is delegated to a specific class that I can easily reuse everywhere.

Moreover, I can extract a method to set the common values for the builders, so I don’t have to set the continent for each manufacturer.

How I implement the ManufacturerListBuilder? It was very simple, the core of the solution is the add method:

But there is a problem, the withContinent method works only if invoked before adding elements to the list, or wait, this is a bug or a feature? This permits me to use multiple continents in the same builder:

So, to better dress the bug to a beautiful feature I renamed the method to withinContinent.

But how this code will looks in Kotlin? Without any refactoring we can use the builder as below:

But in Kotlin we don’t need builders, because we can rely on named parameters.

So we can delete everything and write:

But we miss a feature, we cannot build Manufacturer instances without repeating the continent. We can solve this using Sealed classes, that are used for representing restricted class hierarchies, when a value can have one of the types from a limited set, but cannot have any other type.

So we transform the Manufacturer from a data to a sealed class and we define the class hierarchies, one for each continent:

I’m still not happy, I don’t like to repeat the parameters in the constructor, but I can avoid them defining all the constructor parameters as abstract fields except the field that I must set as default:

Now the code looks pretty good!

What we are doing? We are doing Object-Oriented Programming, we are using polymorphism.

Defining a class that refers to a continent enable us of using pattern matching, so we can do some kind of magic like filtering all manufacturer by type:

Describing it using pattern matching:

And many others magics ;)

Further reading

In the past, I wrote two articles like that, unfortunately, they are in Italian, but there is a lot of code, so you can understand them even just by reading the code ;)

Open-space invader, bug hunter and software writer