Boas práticas e padrões · Padrões estruturais · 4 min de leitura
Proxy
Um substituto com a mesma interface controla o acesso ao objeto real: carrega sob demanda, protege, guarda em cache ou chama pela rede.
Arraste para o lado para ver o diagrama inteiro.
Tipos comuns
- Virtual: cria o objeto caro só no primeiro uso (lazy loading).
- Proteção: confere permissão antes de repassar a chamada.
- Remoto: parece local, mas fala com um serviço pela rede (clientes gRPC, Retrofit).
- Cache: devolve o resultado guardado.
Proxy x Decorator
A estrutura é a mesma (mesma interface, embrulha outro objeto). A diferença é a intenção: o Decorator acrescenta comportamento; o Proxy controla o acesso ao objeto real e muitas vezes gerencia o ciclo de vida dele.
No código
interface Relatorio { fun gerar(): ByteArray }
class RelatorioPesado(private val db: Database) : Relatorio {
override fun gerar() = db.consultaDeMinutos().paraPdf()
}
class RelatorioProtegido(private val real: Relatorio, private val usuario: Usuario) : Relatorio {
override fun gerar(): ByteArray {
check(usuario.temPermissao("relatorios")) { "acesso negado" }
return real.gerar()
}
}
// proxy virtual: o objeto caro só nasce no primeiro uso
val relatorio: Relatorio by lazy { RelatorioPesado(db) } A tela recebe um Relatorio; quem monta (DI) decide se vem protegido, preguiçoso ou os dois, sem a tela mudar.
Em resumo
- Mesma interface do objeto real.
- Controla quando e se o real é criado ou chamado.
- Lazy loading, permissão, chamada remota, cache.
- Kotlin: by lazy é um proxy virtual pronto.