Construir objetos complejos con múltiples parámetros opcionales puede volverse caótico si dependemos solo de constructores tradicionales. El patrón Builder resuelve este problema al permitir una construcción progresiva, donde cada paso es opcional y la creación final del objeto queda encapsulada en un único método. A continuación se explica cómo implementarlo paso a paso dentro de una arquitectura real.
¿Cómo se estructura el patrón Builder dentro de una clase?
La implementación parte de una clase modelo, en este caso User, que representa un usuario con dos propiedades: username y password, ambas de tipo String [01:06]. Lo fundamental es que el constructor de la clase se declara como privado, de modo que nadie pueda crear instancias directamente; la única vía es a través del Builder [05:20].
Dentro de User se crea una inner class llamada Builder [01:50]. Esta clase interna replica las mismas variables del objeto padre, pero con la posibilidad de asignarles valores por defecto o declararlas como opcionales. Por ejemplo:
username puede tener un valor por defecto vacío.
password se declara como opcional (String?) y se inicializa en null [02:30].
Esta separación permite que el consumidor decida qué campos completar sin estar obligado a llenar todos los parámetros.
¿Qué rol cumplen las funciones set dentro del Builder?
Cada propiedad expone una función setter que retorna la misma instancia del Builder [03:00]. Esto es clave para habilitar el encadenamiento de llamadas, conocido como method chaining:
kotlin
class User private constructor(
private val username: String,
private val password: String
) {
class Builder {
private var username: String = ""
private var password: String? = null
fun setUsername(newUsername:String):Builder{this.username= newUsername
returnthis} fun setPassword(newPassword:String):Builder{this.password= newPassword
returnthis} fun build():User{returnUser(username, password ?:"")}}
}
Al retornar Builder en cada setter, es posible seguir editando otros parámetros en la misma cadena sin perder la referencia al objeto en construcción [03:30].
¿Cómo se maneja un password nulo con el Elvis operator?
Cuando password es opcional y podría llegar como null, se utiliza el Elvis operator (?:) [04:48]. Este operador evalúa la expresión de la izquierda; si es nula, devuelve el valor de la derecha:
kotlin
password ?: ""
De esta forma el objeto User siempre recibe un String válido, sin necesidad de modificar la firma del constructor principal.
¿Por qué el constructor privado es esencial en este patrón?
Sin un constructor privado, cualquier parte del código podría instanciar User directamente pasando valores arbitrarios [05:08]. Al marcarlo como private, se fuerza el uso exclusivo del Builder:
kotlin
val user = User.Builder()
.setUsername("hola")
.setPassword("abc123")
.build()
Esto garantiza que la construcción siempre siga el flujo controlado. Además, permite crear un usuario sin contraseña simplemente omitiendo .setPassword() [06:00]. El Builder se encarga de asignar el valor por defecto.
¿Cómo escala el Builder cuando hay muchos parámetros?
En el proyecto se muestra la clase TransferAccount, que contiene múltiples propiedades: username, profile, photo, URL, bankName y más [06:30]. Aquí el patrón brilla con mayor fuerza:
El Builder define un parámetro obligatorio (accountId) dentro de su bloque init, que se solicita al momento de la instanciación [06:52].
El resto de propiedades se configura mediante funciones set encadenables.
Se utiliza la función apply, una scope function de Kotlin que simplifica la asignación de propiedades dentro del Builder [07:10].
Es importante recordar que los patrones de diseño se pueden combinar entre sí. Usar un Singleton junto con un Builder es perfectamente válido siempre que resuelva una necesidad concreta del proyecto [00:40].
Si ya implementaste el patrón Builder en algún proyecto, comparte tu experiencia y cuéntanos cómo manejaste los parámetros opcionales en tu caso.
Nunca me habían explicado este patrón de diseño tan bien, la verdad me parece que es muy útil, está genial.
Es muy buena la forma de explicar de Cristian, ya que luego de tocar el código hace una revisión donde lo explica nuevamente muy tranquilo, he entendido cosas que no entendía de otros cursos de la carrera Android (la estoy haciendo toda)
Al colocal el contructor en private no podemos instancia la clase sino atraves de builder
Kotlin ya nos da la posibilidad de tener parámetros opcionales, así que no veo mucho la ayuda del builder. 🤔
Si, exactamente, por esa razón también existe la lectura de la inline function apply que realmente es un builder. La idea con el curso es mostrar la base del patrón de diseño, por eso implementamos un builder, para que se entienda que pasa realmente.