Sobes.tech
Middle

Welche Entwurfsmuster können in der Kotlin-Sprache verwendet werden?

sobes.tech KI

Antwort von AI

In Kotlin werden häufig folgende Muster angewendet:

  • Singleton: Wird einfach durch object realisiert.
    object MeinSingleton {
        fun machEtwas() {
            // ...
        }
    }
    
  • Factory Method: Verwendet eine abstrakte Funktion in der Superklasse oder Schnittstelle, die von Unterklassen zur Objekterstellung implementiert wird.
    interface Produkt {
        fun operation()
    }
    
    class KonkretesProduktA : Produkt {
        override fun operation() {
            // ...
        }
    }
    
    abstract class Erzeuger {
        abstract fun FabrikMethode(): Produkt
    
        fun someOperation(): Produkt {
            val produkt = FabrikMethode()
            // ...
            return produkt
        }
    }
    
    class KonkreterErzeugerA : Erzeuger() {
        override fun FabrikMethode(): Produkt {
            return KonkretesProduktA()
        }
    }
    
  • Abstract Factory: Gruppe von Fabriken zur Erstellung verwandter Objektfamilien.
    interface AbstraktesProduktA {
        funtzlicheFunktionA()
    }
    
    interface AbstraktesProduktB {
        funtzlicheFunktionB()
        fun eineWeitereNützlicheFunktionB(Kollaborateur: AbstraktesProduktA)
    }
    
    interface AbstrakteFabrik {
        fun createProduktA(): AbstraktesProduktA
        fun createProduktB(): AbstraktesProduktB
    }
    
    // Konkrete Implementierungen von Produkten und Fabriken...
    
  • Builder: Vereinfacht die schrittweise Erstellung komplexer Objekte.
    class Pizza private constructor(
        val kruste: String,
        val soße: String?,
        val toppings: List<String>
    ) {
        data class Builder(
            var kruste: String = "dünn",
            var soße: String? = null,
            val toppings: MutableList<String> = mutableListOf()
        ) {
            fun mitKruste(kruste: String) = apply { this.kruste = kruste }
            fun mitSoße(soße: String) = apply { this.soße = soße }
            fungeToppingHinzu(topping: String) = apply { this.toppings.add(topping) }
            fun build() = Pizza(kruste, soße, toppings)
        }
    }
    
    fun main() {
        val pizza = Pizza.Builder()
            .mitKruste("dick")
            .mitSoße("Tomate")
            .fügeToppingHinzu("Pepperoni")
            .fügeToppingHinzu("Pilze")
            .build()
        // ... Pizza verwenden
    }
    
  • Adapter: Ermöglicht die Zusammenarbeit von Objekten mit inkompatiblen Schnittstellen.
    open class Adaptee {
        fun spezifischeOperation() {
            // ...
        }
    }
    
    interface Target {
        fun operation()
    }
    
    class Adapter(private val adaptee: Adaptee) : Target {
        override fun operation() {
            adaptee.spezifischeOperation()
        }
    }
    
  • Decorator: Fügt bestehenden Objekten neue Funktionen hinzu, ohne ihre Struktur zu verändern. Erweiterungen und Delegierung in Kotlin erleichtern dies erheblich.
    interface DataSource {
        fun readData(): String
        fun writeData(data: String)
    }
    
    class FileDataSource(private val dateiName: String) : DataSource {
        override fun readData(): String {
            // Aus Datei lesen
            return ""
        }
    
        override fun writeData(data: String) {
            // In Datei schreiben
        }
    }
    
    class EncryptionDecorator(private val source: DataSource) : DataSource by source {
        override fun readData(): String {
            // Daten entschlüsseln
            val data = source.readData()
            return data // entschlüsselte Daten
        }
    
        override fun writeData(data: String) {
            // Daten verschlüsseln
            source.writeData(data) // verschlüsselte Daten
        }
    }
    
  • Observer: Definiert die "1 zu vielen"-Abhängigkeit. Coroutines Flow und delegated properties in Kotlin können für die Implementierung genutzt werden.
    // Einfache Implementierung ohne Flow
    interface Observer {
        fun update(message: String)
    }
    
    class Subject {
        private val observers = mutableListOf<Observer>()
    
        fun attach(observer: Observer) {
            observers.add(observer)
        }
    
        fun detach(observer: Observer) {
            observers.remove(observer)
        }
    
        fun notifyObservers(message: String) {
            observers.forEach { it.update(message) }
        }
    }
    
  • Strategy: Definiert eine Familie von Algorithmen, kapselt jeden und macht sie austauschbar.
    interface PaymentStrategy {
        fun pay(amount: Double)
    }
    
    class PayByCreditCard(private val cardNumber: String) : PaymentStrategy {
        override fun pay(amount: Double) {
            println("Zahle $amount mit Kreditkarte $cardNumber")
        }
    }
    
    class PayByPayPal(private val email: String) : PaymentStrategy {
        override fun pay(amount: Double) {
            println("Zahle $amount mit PayPal $email")
        }
    }
    
    class Order(private val paymentStrategy: PaymentStrategy) {
        fun processOrder(amount: Double) {
            // ... Bestellverarbeitung
            paymentStrategy.pay(amount)
        }
    }
    
  • State: Ermöglicht einem Objekt, sein Verhalten je nach internem Zustand zu ändern. Sealed classes und when-Ausdrücke vereinfachen die Implementierung.
    sealed class State {
        object Idle : State()
        object Loading : State()
        data class Error(val message: String) : State()
        data class Success(val data: Any) : State()
    }
    
    class Context {
        var state: State = State.Idle
    
        fun handleEvent() {
            when (state) {
                State.Idle -> {
                    println("Ereignis im Idle-Zustand")
                    state = State.Loading
                }
                State.Loading -> {
                    println("Ereignis im Lade-Zustand, ignorieren")
                }
                is State.Error -> {
                    println("Ereignis im Fehler-Zustand: ${state.message}")
                    // Möglicher Übergang in einen anderen Zustand
                }
                is State.Success -> {
                    println("Ereignis im Erfolg-Zustand: ${state.data}")
                    // Möglicher Übergang in einen anderen Zustand
                }
            }
        }
    }