Delegasjonsmønster i Kotlin

1. Oversikt

Det er mange brukstilfeller der delegering foretrekkes fremfor arv. Kotlin har god språknivå støtte for dette.

I denne veiledningen, Vi snakker om Kotlins opprinnelige støtte til delegasjonsmønsteret og se det i aksjon.

2. Implementering

La oss først anta at vi har et kodeeksempel med strukturen nedenfor i et tredjepartsbibliotek:

grensesnitt Produsent {fun produce (): String} class ProducerImpl: Producer {override fun produce () = "ProducerImpl"}

Neste, la oss dekorere den eksisterende implementeringenved å bruke nøkkelordet og legg til den ekstra nødvendige behandlingen:

klasse EnhancedProducer (privat val delegat: produsent): produsent av delegat {override fun produce () = "$ {delegate.produce ()} og EnhancedProducer"}

Så i dette eksemplet har vi antydet at EnhancedProducer klasse vil kapsle inn a delegat objekt av typen Produsent. Og det kan også bruke funksjonalitet fra Produsent gjennomføring.

Til slutt, la oss kontrollere at det fungerer som forventet:

val producer = EnhancedProducer (ProducerImpl ()) assertThat (producer.produce ()). isEqualTo ("ProducerImpl and EnhancedProducer")

3. Bruk saker

La oss nå se på to vanlige brukssaker for delegeringsmønsteret.

Først kan vi bruke delegeringsmønsteret å implementere flere grensesnitt ved hjelp av eksisterende implementeringer:

klasse CompositeService: UserService av UserServiceImpl (), MessageService av MessageServiceImpl ()

For det andre kan vi bruke delegering for å forbedre en eksisterende implementering.

Det siste er hva vi gjorde i forrige avsnitt. Men et mer virkelig eksempel som det nedenfor er spesielt nyttig når vi ikke kan endre en eksisterende implementering - for eksempel tredjepartsbibliotekekode:

class SynchronizedProducer (private val delegate: Producer): Producer by delegate {private val lock = ReentrantLock () override fun produce (): String {lock.withLock {return delegate.produce ()}}}

4. Delegasjon er ikke arv

Nå må vi alltid huske det delegaten vet ingenting om dekoratøren. Så vi skal ikke prøve GoF-malmetode-liknende tilnærming med dem.

La oss vurdere et eksempel:

grensesnitt Service {val seed: Int fun serve (action: (Int) -> Unit)} class ServiceImpl: Service {override val seed = 1 override fun serve (action: (Int) -> Unit) {action (seed)}} class ServiceDecorator: Service by ServiceImpl () {override val seed = 2}

Her delegaten (ServiceImpl) bruker en egenskap definert i det felles grensesnittet, og vi overstyrer den i dekoratøren (ServiceDecorator). Imidlertid påvirker det ikke delegatens behandling:

val service = ServiceDecorator () service.serve {assertThat (it) .isEqualTo (1)}

Til slutt er det viktig å merke seg at i Kotlin, Vi kan delegere ikke bare til grensesnitt, men også til å skille egenskaper.

5. Konklusjon

I denne opplæringen snakket vi om Kotlin-grensesnittdelegering - når den skal brukes, hvordan du konfigurerer den og dens forbehold.

Som vanlig er den komplette kildekoden for denne artikkelen tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found