Kotlin Academy · Lektion

Praktiska mönster

Dekoratorer med delegering

Lektion 4 av 413 steg

Praktiska mönster är en gratis lektion i Kotlin Academy på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Kotlin Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Kotlin Academy innehåller totalt 4 lektioner.

Dekoratörsmönstret

En dekoratör omsluter ett objekt för att lägga till beteende samtidigt som samma gränssnitt behålls. Kotlin:s nyckelord by gör dekoratörer mycket enkla: vidarebefordra allt och åsidosätt bara de delar ni förbättrar.

En baskomponent

Vi börjar med en enkel datakälla. Dekoratörerna kommer att omsluta den.

interface DataSource {
    fun fetch(): String
}

class NetworkSource : DataSource {
    override fun fetch() = "raw-data"
}

fun main() {
    println(NetworkSource().fetch())
}

En loggningsdekoratör

Dekoratören delegerar till den omslutna källan och lägger till loggning runt det anrop som är relevant.

interface DataSource { fun fetch(): String }
class NetworkSource : DataSource { override fun fetch() = "raw-data" }

class LoggingSource(private val inner: DataSource) : DataSource by inner {
    override fun fetch(): String {
        println("fetching...")
        val result = inner.fetch()
        println("done")
        return result
    }
}

fun main() {
    println(LoggingSource(NetworkSource()).fetch())
}

En cachningsdekoratör

En annan dekoratör cachar det första resultatet, så att upprepade anrop hoppar över den underliggande källan.

interface DataSource { fun fetch(): String }
class NetworkSource : DataSource { override fun fetch() = "raw-data" }

class CachingSource(private val inner: DataSource) : DataSource by inner {
    private var cached: String? = null
    override fun fetch(): String {
        return cached ?: inner.fetch().also { cached = it }
    }
}

fun main() {
    val s = CachingSource(NetworkSource())
    println(s.fetch())
    println(s.fetch()) // served from cache
}

Stapla dekoratörer

Eftersom varje dekoratör själv är en DataSource kan ni stapla dem. Ordningen spelar roll: den yttre omsluter den inre.

interface DataSource { fun fetch(): String }
class NetworkSource : DataSource { override fun fetch() = "raw-data" }

class LoggingSource(private val inner: DataSource) : DataSource by inner {
    override fun fetch(): String { println("log"); return inner.fetch() }
}
class CachingSource(private val inner: DataSource) : DataSource by inner {
    private var c: String? = null
    override fun fetch() = c ?: inner.fetch().also { c = it }
}

fun main() {
    val s = LoggingSource(CachingSource(NetworkSource()))
    println(s.fetch())
    println(s.fetch())
}

En valideringsdekoratör

Dekoratörer kan också kontrollera indata. Här validerar en dekoratör innan den delegerar till den riktiga arbetaren.

interface Processor { fun process(input: String): String }
class UpperProcessor : Processor { override fun process(input: String) = input.uppercase() }

class ValidatingProcessor(private val inner: Processor) : Processor by inner {
    override fun process(input: String): String {
        require(input.isNotBlank()) { "empty input" }
        return inner.process(input)
    }
}

fun main() {
    println(ValidatingProcessor(UpperProcessor()).process("hello"))
}

Omslutare för skrivskyddad samling

Delegering gör det enkelt att skapa adapter-wrappers. Här omsluter vi en lista och lägger till en anpassad sammanfattningsmetod samtidigt som alla listoperationer vidarebefordras.

class SummarizedList(private val inner: List<Int>) : List<Int> by inner {
    fun total() = inner.sum()
}

fun main() {
    val list = SummarizedList(listOf(1, 2, 3))
    println(list.size)
    println(list.total())
}

Räkna anrop

En dekoratör kan hålla reda på mätvärden på ett transparent sätt, vilket är användbart för övervakning utan att den riktiga implementationen behöver ändras.

interface Service { fun call(): String }
class RealService : Service { override fun call() = "ok" }

class CountingService(private val inner: Service) : Service by inner {
    var calls = 0
        private set
    override fun call(): String {
        calls++
        return inner.call()
    }
}

fun main() {
    val s = CountingService(RealService())
    s.call(); s.call()
    println(s.calls)
}

Varför delegering passar bäst här

Om ni bygger dekoratörer med arv måste basklassen vara open, och varje dekoratör binds till en konkret klass. Delegering är endast beroende av gränssnittet, så dekoratörerna förblir löst kopplade och kan komponeras.

Checklista för mönstret

Så här bygger ni en delegeringsdekoratör:

  • Ta det omslutna objektet som en private val
  • Delegera gränssnittet med by
  • Åsidosätt bara de medlemmar ni förbättrar
  • Anropa det inre objektet i åsidosättningen

Knyta ihop det

Dekoratörer, adaptrar och proxyer följer naturligt av klassdelegering. Tillsammans med små gränssnitt låter de er bygga flexibla system i lager som är enkla att testa och utöka.

Snabbtest

Testa er förståelse av praktiska delegeringsmönster.

Sammanfattning

Ni byggde praktiska dekoratörer med delegering:

  • Omslutare för loggning, cachning, validering och räkning
  • Stapla dekoratörer eftersom varje dekoratör använder samma gränssnitt
  • Åsidosätt bara förbättrade medlemmar och vidarebefordra resten

Detta avslutar kursen om klassdelegering.

Gratis att börja

Lär dig Kotlin med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
51
Lektioner
203

Vanliga frågor

Är lektionen ”Praktiska mönster” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Kotlin Academy, inklusive ”Praktiska mönster”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Kotlin Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Praktiska mönster”?

Dekoratorer med delegering Ni övar på Kotlin Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Kotlin Academy?

Du behöver inga förkunskaper. Utbildningen i Kotlin Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Praktiska mönster”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Kotlin Academy-lektionen?

Ja. Varje Kotlin Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Nyckelordet by
  2. Delegera till medlemmar
  3. Delegering jämfört med arv
  4. Praktiska mönster
← Tillbaka till Kotlin Academy