Sitemap

Builder Pattern

2 min readMay 16, 2026

--

Before understanding Builder Pattern, first understand the problem it solves.

Press enter or click to view image in full size

1. Problem Without Builder

Suppose we have a User class.

class User(
val name: String,
val age: Int,
val email: String?,
val phone: String?,
val address: String?
)

Now create an object:

val user = User(
“Suman”,
29,
“suman@gmail.com”,
null,
“India”
)

But imagine real Android classes with:

  • 10–15 fields
  • optional values
  • configs
  • flags
  • headers
  • retry counts

Then constructor becomes ugly:

User(
"Suman",
29,
null,
null,
"India",
true,
false,
3000,
5
)

Problems:

  • Hard to read
  • Hard to remember parameter order
  • Many nulls
  • Easy to make mistakes

2. Builder Pattern Solution

Instead of passing everything in constructor:

val user = User.Builder()
.setName("Suman")
.setAge(29)
.setAddress("India")
.build()

Now code is:

  • readable
  • clean
  • flexible

This is Builder Pattern.

3. Real Meaning of Builder Pattern

Builder Pattern means:

Create object step-by-step.

Instead of constructing everything at once.

Get Suman Shil’s stories in your inbox

Join Medium for free to get updates from this writer.

Very common in Android because Android objects usually have many configurations.

Let’s Implement Our Own Builder

We’ll create a User object properly.

class User private constructor(
val name:String,
val age:Int
)

Why private constructor?

Because we want users to create object only using Builder.
NOT like this:

User(…)

You must create object using:

User.Builder().build()

Basic Builder Code in Kotlin:

class User private constructor(
val name:String,
val age:Int,
val email:String?
){
class Builder{
private val name:String,
private val age:Int,
private val email : String?= null

fun setName(name:String) = {
this.name = name
}
fun setAge(age: Int) = apply {
this.age = age
}
fun setEmail(email: String) = apply {
this.email = email
}
fun build():User{
return User(name,age,email)
}
}

Usage:

fun main() {
val user = User.Builder()
.setName("Suman")
.setAge(29)
.setEmail("suman@gmail.com")
.build()
println(user.name)
println(user.age)
}

What is apply?
This:

fun setName(name: String) = apply {
this.name = name
}

allows chaining:

val user = User.Builder()
.setName("Suman")
.setAge(29)
.build()

Without apply, you would need:

val builder = User.Builder()
builder.setName("Suman")
builder.setAge(29)
val user = builder.build()

Add Validation

Builder becomes more useful when we validate before creating object.

fun build(): User {
require(name.isNotBlank()) {
"Name is required"
}

require(age > 0) {
"Age must be greater than 0"
}

return User(name, age, email, phone, address)
}
val user = User.Builder()
.setAge(29)
.build()

🎯 Final Thought

Builder Pattern is not just about avoiding large constructors — it helps create cleaner, more readable, and scalable Android APIs.

The real understanding comes when you ask:

👉 “Will this object become difficult to configure or maintain as it grows?”

That’s where Builder Pattern shines.

From AlertDialog to Retrofit and WorkManager, this pattern is everywhere in Android development.

If you found this helpful, follow me on Medium for more simple Android tutorials, system design concepts, and production-level Kotlin tips.

Happy coding! 🚀

--

--