Patrón Builder en Kotlin: guía paso a paso con código

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué Builder en Kotlin no es solo un "copia y pega" de Java?



Si alguna vez has programado en Java, seguramente te has encontrado con el patrón Builder clásico. Decenas de líneas de código, clases estáticas internas, métodos set y el build() final. Todo funciona, pero resulta engorroso.



Ahora imagina que te has pasado a Kotlin. Un lenguaje creado para ser conciso y expresivo. Y te enfrentas a la tarea de crear un objeto con múltiples parámetros, algunos de los cuales son opcionales. Tu mano se estira para escribir el Builder clásico de Java...



¡Alto! En Kotlin, este patrón se puede implementar de forma 10 veces más simple, elegante y segura. En este artículo, analizaremos 4 formas de implementar el patrón Builder en Kotlin, desde la más simple hasta el enfoque avanzado con DSL.



Este material se basa en una pregunta real de Stack Overflow que ha obtenido miles de visitas. Lo hemos adaptado para contenido educativo, para que puedas aplicar los conocimientos de inmediato en la práctica.



El problema: ¿cuándo se necesita un Builder?



Imagina que tienes una clase Pizza:



class Pizza(    val size: String,    val cheese: Boolean = false,    val pepperoni: Boolean = false,    val mushrooms: Boolean = false,    val olives: Boolean = false,    val extraCheese: Boolean = false)


En apariencia, todo está bien. Pero cuando creas una pizza con 5 parámetros opcionales, el código se vuelve ilegible:



val pizza = Pizza("Large", true, false, true, false, true)


Buscar con los ojos qué significa cada parámetro es agotador. Aquí es donde el patrón Builder viene al rescate.



Forma 1. Builder clásico estilo Java (para compatibilidad)



Si necesitas mantener compatibilidad con código Java o deseas una API explícita al máximo, puedes usar el enfoque clásico:



class Pizza private constructor(    val size: String,    val cheese: Boolean,    val pepperoni: Boolean,    val mushrooms: Boolean,    val olives: Boolean,    val extraCheese: Boolean) {    class Builder(private val size: String) {        private var cheese: Boolean = false        private var pepperoni: Boolean = false        private var mushrooms: Boolean = false        private var olives: Boolean = false        private var extraCheese: Boolean = false

fun cheese(value: Boolean) = apply { cheese = value } fun pepperoni(value: Boolean) = apply { pepperoni = value } fun mushrooms(value: Boolean) = apply { mushrooms = value } fun olives(value: Boolean) = apply { olives = value } fun extraCheese(value: Boolean) = apply { extraCheese = value }

fun build() = Pizza(size, cheese, pepperoni, mushrooms, olives, extraCheese) }}

// Uso:val pizza = Pizza.Builder("Large") .cheese(true) .pepperoni(true) .mushrooms(true) .build()


Ventajas: código obvio, comprensible para desarrolladores de Java.
Desventajas: mucho código boilerplate, no aprovecha las capacidades de Kotlin.



Forma 2. Estilo Kotlin con argumentos nombrados y valores por defecto



La forma más simple y a menudo la mejor es no usar un Builder en absoluto, sino confiar en las capacidades del propio lenguaje:



data class Pizza(    val size: String,    val cheese: Boolean = false,    val pepperoni: Boolean = false,    val mushrooms: Boolean = false,    val olives: Boolean = false,    val extraCheese: Boolean = false)

// Uso:val pizza = Pizza( size = "Large", cheese = true, pepperoni = true, mushrooms = true)


Este es un código limpio, legible y type-safe. Los argumentos nombrados de Kotlin resuelven el problema de los "números mágicos" y el orden de los parámetros.



Blogs

Book Recommendations