Design Patterns in Kotlin with Code Examples

онлайн тренажер по питону

Design Patterns in Kotlin with Examples



Design patterns are proven solutions to typical problems in software development. They help create flexible, scalable, and maintainable architecture. In Kotlin, thanks to its concise syntax and functional capabilities, many classic patterns are implemented particularly elegantly. In this article, we will examine three key patterns: Singleton, Factory Method, and Observer, and show their implementation in Kotlin with practical examples.



1. Singleton



The Singleton pattern guarantees that a class has only one instance and provides a global access point to it. In Kotlin, there is a built-in construct for this — object. It creates a thread-safe singleton without extra code.



Implementation in Kotlin



The simplest way to declare a singleton is to use the object keyword:



object DatabaseConfig {    private val url = "jdbc:postgresql://localhost:5432/mydb"    private val username = "admin"    private val password = "secret"

fun connect(): String { return "Connection to $url as $username" }}

fun main() { println(DatabaseConfig.connect()) // Output: Connection to jdbc:postgresql://localhost:5432/mydb as admin}


If you need a classic Singleton with a private constructor (for example, to inherit from another class), use a 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("Application started")}


The advantage of the by lazy approach is lazy initialization, which is performed only on the first access.



2. Factory Method



The Factory Method pattern defines an interface for creating an object but allows subclasses to alter the type of object that will be created. In Kotlin, this is often implemented using sealed class or interfaces.



Implementation in Kotlin



Suppose we are developing a notification system. We have different types of notifications: Email, SMS, and Push. Let's create a factory to generate them.



// Interface for all notificationsinterface Notification {    fun send(message: String)}

// Concrete implementationsclass EmailNotification : Notification { override fun send(message: String) { println("Sending Email: $message") }}

class SMSNotification : Notification { override fun send(message: String) { println("Sending SMS: $message") }}

class PushNotification : Notification { override fun send(message: String) { println("Sending Push notification: $message") }}

// Factoryobject NotificationFactory { fun createNotification(type: String): Notification { return when (type.lowercase()) { "email" -> EmailNotification() "sms" -> SMSNotification() "push" -> PushNotification() else -> throw IllegalArgumentException("Unknown notification type: $type") } }}

fun main() { val notification = NotificationFactory.createNotification("sms") notification.send("Your confirmation code: 1234") // Output: Sending SMS: Your confirmation code: 1234}


If the number of types is fixed, it's better to use a sealed class for greater safety:



sealed class NotificationType {    object Email : NotificationType()    object SMS : NotificationType()    object Push : NotificationType()}

fun createNotification(type: NotificationType): Notificat

Похожие статьи

Книги по Python