Pular para o conteúdo

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.

Código cliente → RequestBuilder: url(), header()url(), header()1RequestBuilder → build()2build() → Request3Código clienteCódigo clienteRequestBuilder — url, headers, timeoutRequestBuilderurl, headers, timeoutbuild() — validabuild()validaRequest — imutávelRequestimutável

Arraste para o lado para ver o diagrama inteiro.

O cliente informa só o que importa; o build() aplica os padrões, valida e devolve um objeto pronto e imutável.

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

✓ ExemploKotlin
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

Referências

Continue aprendendo

Todos os temas de boas práticas e padrões →