Boas práticas e padrões · Padrões de criação · 4 min de leitura
Builder
Monta objetos complexos passo a passo, com valores padrão e validação no final, sem construtores com dez parâmetros.
Arraste para o lado para ver o diagrama inteiro.
Para que serve
Objetos com muitos campos opcionais (requisições HTTP, notificações, consultas) viram construtores ilegíveis: Request(url, null, null, 30, true, false). O builder dá nome a cada passo e valida tudo de uma vez no final. OkHttp, Retrofit e NotificationCompat.Builder no Android usam o padrão.
Em Kotlin
Parâmetros nomeados com valores padrão e data class + copy() resolvem a maioria dos casos sem builder. Quando a construção é longa ou condicional, um DSL com lambda (buildString { }, request { }) é o builder idiomático.
No código
class Requisicao private constructor(val url: String, val headers: Map<String, String>, val timeoutS: Int) {
class Builder {
private var url: String? = null
private val headers = mutableMapOf<String, String>()
private var timeoutS = 30
fun url(u: String) = apply { url = u }
fun header(k: String, v: String) = apply { headers[k] = v }
fun timeout(s: Int) = apply { timeoutS = s }
fun build(): Requisicao {
val u = requireNotNull(url) { "url obrigatória" }
require(timeoutS in 1..120) { "timeout fora do limite" }
return Requisicao(u, headers.toMap(), timeoutS)
}
}
}
fun requisicao(bloco: Requisicao.Builder.() -> Unit) = Requisicao.Builder().apply(bloco).build()
val r = requisicao { url("https://api.exemplo.com"); header("Accept", "application/json") } O construtor é privado: não existe Requisicao inválida. A função requisicao { } vira um pequeno DSL.
Em resumo
- Nomeia cada parte da construção.
- Valida tudo no build(); o objeto final é imutável.
- Kotlin: parâmetros nomeados resolvem o caso simples.
- DSL com lambda é o builder idiomático em Kotlin.