Padrões de Design em Kotlin: Técnicas Avançadas com Exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Padrões de Design em Kotlin com Exemplos: Nível Avançado

\n\n

Padrões de design são soluções comprovadas para problemas típicos no desenvolvimento de software. Se você já domina os padrões básicos (Singleton, Factory, Observer), é hora de passar para o próximo nível. Neste artigo, vamos explorar quatro padrões avançados — Cadeia de Responsabilidade, Interpretador, Mediador e Snapshot — e mostrar sua implementação em Kotlin, considerando as expressões idiomáticas da linguagem (sealed class, extension functions, lambdas).

\n\n

1. Cadeia de Responsabilidade (Chain of Responsibility)

\n\n

Propósito: Permite passar uma solicitação sequencialmente por uma cadeia de manipuladores até que um deles a processe.

\n\n

Problema: Um sistema de logging onde mensagens de diferentes níveis (DEBUG, INFO, ERROR) devem ser processadas por diferentes loggers.

\n\n

Implementação em Kotlin:

\n\n
// Manipulador abstrato\nabstract class Logger(private val level: Int) {\n    private var nextLogger: Logger? = null\n\n    fun setNext(logger: Logger): Logger {\n        this.nextLogger = logger\n        return logger\n    }\n\n    fun log(level: Int, message: String) {\n        if (this.level <= level) {\n            write(message)\n        }\n        nextLogger?.log(level, message)\n    }\n\n    protected abstract fun write(message: String)\n}\n\n// Manipuladores concretos\nclass ConsoleLogger(level: Int) : Logger(level) {\n    override fun write(message: String) = println("[Console] $message")\n}\n\nclass FileLogger(level: Int) : Logger(level) {\n    override fun write(message: String) = println("[File] $message")\n}\n\nclass EmailLogger(level: Int) : Logger(level) {\n    override fun write(message: String) = println("[Email] $message")\n}\n\n// Uso\nfun main() {\n    val logger = ConsoleLogger(1).apply {\n        setNext(FileLogger(2))\n            .setNext(EmailLogger(3))\n    }\n    logger.log(2, "Aviso: baixo nível de memória")\n    // Saída:\n    // [Console] Aviso: baixo nível de memória\n    // [File] Aviso: baixo nível de memória\n}
\n\n

Vantagens em Kotlin: Graças ao apply e à chamada encadeada de setNext, o código fica conciso. Também é possível substituir a classe abstrata por uma interface com implementação padrão.

\n\n

2. Interpretador (Interpreter)

\n\n

Propósito: Define uma gramática para uma linguagem e interpreta sentenças dessa linguagem.

\n\n

Problema: Necessidade de analisar e calcular expressões aritméticas simples (por exemplo, "3 + 5 - 2").

\n\n

Implementação em Kotlin com sealed class:

\n\n
// Expressão abstrata\nsealed class Expression {\n    abstract fun interpret(): Int\n}\n\n// Expressão terminal — número\ndata class Number(val value: Int) : Expression() {\n    override fun interpret() = value\n}\n\n// Expressões não terminais — operações\ndata class Add(val left: Expression, val right: Expression) : Expression() {\n    override fun interpret() = left.interpret() + right.interpret()\n}\n\ndata class Subtract(val left: Expression, val right: Expression) : Expression() {\n    override fun interpret() = left.interpret() - right.interpret()\n}\n\n// Analisador (simplificado)\nfun parse(tokens: List<String>): Expression {\n    val stack = mutableListOf<Expression>()\n    var i = 0\n    while (i < tokens.size) {\n        when (tokens[i]) {\n            "+" -> {\n                val right = Number(tokens[++i].toInt())\n                val left = stack.removeLast()\n                stack.add(Add(left, right))\n            }\n            "-" -> {\n                val right = Number(tokens[++i].toInt())\n                val left = stack.removeLast()\n                stack.add(Subtract(left, right))\n            }\n            else -> stack.add(Number(tokens[i]                

Blogs

Book Recommendations