Delegationsmønster i Kotlin

1. Oversigt

Der er mange brugssager, hvor delegering foretrækkes frem for arv. Kotlin har god sprogstøtte til dette.

I denne vejledning vi vil tale om Kotlins oprindelige støtte til delegationsmønsteret og se det i aktion.

2. Implementering

Lad os først antage, at vi har et kodeeksempel med nedenstående struktur i et tredjepartsbibliotek:

interface Producer {sjovt producere (): String} klasse ProducerImpl: Producer {tilsidesætte sjovt producere () = "ProducerImpl"}

Næste, lad os dekorere den eksisterende implementeringved hjælp af "efter" nøgleordet og tilføj den yderligere nødvendige behandling:

klasse EnhancedProducer (privat val delegeret: Producer): Producent af delegat {override fun produce () = "$ {delegate.produce ()} og EnhancedProducer"}

Så i dette eksempel har vi angivet, at EnhancedProducer klasse indkapsler en delegeret objekt af typen Producent. Og det kan også bruge funktionalitet fra Producent implementering.

Lad os endelig kontrollere, at det fungerer som forventet:

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

3. Brug sager

Lad os nu se på to almindelige brugssager til delegationsmønsteret.

For det første kan vi bruge delegeringsmønsteret at implementere flere grænseflader ved hjælp af eksisterende implementeringer:

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

For det andet kan vi bruge delegering at forbedre en eksisterende implementering.

Sidstnævnte er, hvad vi gjorde i det foregående afsnit. Men et mere virkeligt eksempel som det nedenfor er især nyttigt, når vi ikke kan ændre en eksisterende implementering - for eksempel tredjepartsbibliotekskode:

klasse SynchronizedProducer (privat val-delegat: producent): producent af delegeret {private val lock = ReentrantLock () tilsidesætter sjov producere (): streng {lock.withLock {return delegate.produce ()}}}

4. Delegation er ikke arv

Nu skal vi altid huske det delegaten ved intet om dekoratøren. Så vi skal ikke prøve GoF-skabelonmetode-lignende tilgang med dem.

Lad os overveje et eksempel:

interface Service {val seed: Int fun serve (action: (Int) -> Unit)} class ServiceImpl: Service {override val seed = 1 override fun serve (action: (Int) -> Unit) {action (seed)}} klasse ServiceDecorator: Service ved ServiceImpl () {tilsidesætte val seed = 2}

Her har delegaten (ServiceImpl) bruger en egenskab, der er defineret i den fælles grænseflade, og vi tilsidesætter den i dekoratøren (ServiceDecorator). Det påvirker dog ikke delegatens behandling:

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

Endelig er det vigtigt at bemærke, at i Kotlin, Vi kan ikke kun delegere til grænseflader, men også til separate egenskaber.

5. Konklusion

I denne vejledning talte vi om Kotlin-interface-delegering - hvornår den skal bruges, hvordan man konfigurerer den og dens forbehold.

Som sædvanlig er den komplette kildekode til denne artikel tilgængelig på GitHub.


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