Builder pattern in Kotlin: to build or not to build.

Serhii Prodan
3 min readApr 9, 2019
Photo by Debby Hudson on Unsplash

Following my previous article: The Builder pattern in Java, and since lately I’m trying to write Kotlin and avoid Java as much as possible (I don’t have any strong opinions against Java per se. It was in fact my first programming language, I just like the expressiveness of Kotlin so much more) I wanted to see if and how Kotlin comes in handy in this case.

To briefly recap, the Builder pattern gives more flexibility when it comes to constructing complex objects, greatly improves readability of code (something I always strive for), supports immutability of classes and scales pretty well. So instead of calling the constructor or a class like so (Java):

Car car = new Car("Ford", "Mustang", 1968, "blue", "fastback", 2, "manual", "V8");

we call the methods of the builder (designed with a fluent interface in mind):

Car car = new Car.Builder("Ford", "Mustang", 1968)
.color("blue")
.bodyType("fastback")
.noOfDoors(2)
.transmission("manual")
.engine("V8")
.build()

It is possible to declare mandatory properties in the constructor the Builder and set the rest with setter functions as needed or leave them to the defaults. There are some cons to the Builder pattern (see the The Builder pattern in Java for more details). In addition to those, the chain of method calls can become quite big depending on the number of properties that we want to set for the class.

Do we need to apply same principles in Kotlin and still use builders? In the brief time that I’m writing Kotlin code I’ve discovered that half of the time applying techniques that are aimed at eliminating Java’s shortcomings and limitations and which we are so used to are not needed in Kotlin.

First let’s create the same class as above but in Kotlin:

data class Car(
val make: String, // mandatory
val model: String, // mandatory
val year: Int, // mandatory
val color: Blue, // optional
val bodyType: String, // optional
val noOfDoors: Int, // optional
val transmission: String, // optional
val engine: String // optional
)

Thanks to the default arguments it is possible to set default values for the optional properties of the function:

fun power(base: Int, power: Int = 2) = TODO()

They are an alternative to method overloading and allow to call the function with only mandatory values, or overload the default ones:

power(8) // => 64
power(6, 3) // => 216

We can do the same with the Car class and set default values directly in the constructor:

data class Car(
val make: String, // mandatory
val model: String, // mandatory
val year: Int, // mandatory
val color: Blue = "", // optional
val bodyType: String = "", // optional
val noOfDoors: Int = 4, // optional
val transmission: String = "", // optional
val engine: String = "" // optional
)

and create the class with only mandatory properties:

val car = Car("Ford", "Mustang", 1968)

or override the ones we need:

val car = Car("Ford", "Mustang", 1968, "blue", "fastback", 2)

But this solves only half the problem. What if we want to provide only some optional parameters without the need to specify all of them? For this Kotlin has named arguments, another very useful feature that Java, unfortunately, lacks, which allows us to provide the parameters to the functions using their names like so:

val car = Car(
make = "Ford",
model = "Mustang",
year = 1968,
color = "blue",
bodyType = "fastback",
noOfDoors = 2,
transmission = "manual",
engine = "V8"
)

Combined with the default arguments we can do things like this:

val car = Car(
make = "Ford",
model = "Mustang",
year = 1968,
engine = "V8"
)

As we can see Kotlin gives us built-in functionality that eliminates the original problems that the Builder pattern is designed to solve. We have good readability of what exactly we’re passing to the constructor, we avoid having multiple constructor overloads, and reduce code.

The only limitation as compared to the builder pattern is that we can’t postpone the creation of the object to a later time like we would with a Java builder:

CarBuilder carBuilder = new Car.Builder("Mercedes", "300 SLR" 1955)
.color("silver");
// do somethingCar car = carBuilder.build();

For this I will write another article on how to create DSL-style builders in Kotlin.

--

--

Serhii Prodan

Searching for the answer to the Ultimate Question by night, tester by calling, serendipitously became a devops lead by day. Automating things I get my hands on.