Padrões de Projeto em Kotlin com Exemplos
Padrões de projeto são soluções comprovadas para problemas típicos no desenvolvimento de software. Eles ajudam a criar uma arquitetura flexível, escalável e de fácil manutenção. Na linguagem Kotlin, graças à sua sintaxe concisa e recursos funcionais, muitos padrões clássicos são implementados de forma especialmente elegante. Neste artigo, vamos analisar três padrões principais: Singleton, Factory Method e Observer, e mostrar sua implementação em Kotlin com exemplos práticos.
1. Singleton
O padrão Singleton garante que uma classe tenha apenas uma instância e fornece um ponto de acesso global a ela. Em Kotlin, existe uma construção nativa para isso — object. Ela cria um singleton thread-safe sem código extra.
Implementação em Kotlin
A maneira mais simples de declarar um singleton é usar a palavra-chave object:
object DatabaseConfig { private val url = "jdbc:postgresql://localhost:5432/mydb" private val username = "admin" private val password = "secret"
fun connect(): String { return "Conexão a $url como $username" }}
fun main() { println(DatabaseConfig.connect()) // Saída: Conexão a jdbc:postgresql://localhost:5432/mydb como admin}Se precisar de um Singleton clássico com construtor privado (por exemplo, para herdar de outra classe), use companion object:
class Logger private constructor() { fun log(message: String) { println("[LOG]: $message") }
companion object { private val instance: Logger by lazy { Logger() }
fun getInstance(): Logger { return instance } }}
fun main() { val logger = Logger.getInstance() logger.log("Aplicação iniciada")}A vantagem da abordagem com by lazy é a inicialização preguiçosa, que é executada apenas no primeiro acesso.
2. Factory Method
O padrão Factory Method define uma interface para criar um objeto, mas permite que subclasses alterem o tipo do objeto criado. Em Kotlin, isso é frequentemente implementado com sealed class ou interfaces.
Implementação em Kotlin
Suponha que estamos desenvolvendo um sistema de notificações. Temos diferentes tipos de notificações: Email, SMS e Push. Vamos criar uma fábrica para gerá-las.
// Interface para todas as notificaçõesinterface Notification { fun send(message: String)}
// Implementações concretasclass EmailNotification : Notification { override fun send(message: String) { println("Enviando Email: $message") }}
class SMSNotification : Notification { override fun send(message: String) { println("Enviando SMS: $message") }}
class PushNotification : Notification { override fun send(message: String) { println("Enviando Push: $message") }}
// Fábricaobject NotificationFactory { fun createNotification(type: String): Notification { return when (type.lowercase()) { "email" -> EmailNotification() "sms" -> SMSNotification() "push" -> PushNotification() else -> throw IllegalArgumentException("Tipo de notificação desconhecido: $type") } }}
fun main() { val notification = NotificationFactory.createNotification("sms") notification.send("Seu código de confirmação: 1234") // Saída: Enviando SMS: Seu código de confirmação: 1234}Se o número de tipos for fixo, é melhor usar sealed class para maior segurança:
sealed class NotificationType { object Email : NotificationType() object SMS : NotificationType() object Push : NotificationType()}
fun createNotification(type: NotificationType): Notificat