Praktyczne wzorce
Dekoratory z delegowaniem
Praktyczne wzorce to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Wzorzec dekoratora
Dekorator opakowuje obiekt, aby dodać zachowanie, zachowując ten sam interfejs. Słowo kluczowe by w Kotlinie sprawia, że tworzenie dekoratorów jest bardzo proste: należy przekazywać dalej wszystko i zastępować tylko te elementy, które są rozszerzane.
Komponent bazowy
Zaczynamy od prostego źródła danych. To źródło zostanie opakowane przez dekoratory.
interface DataSource {
fun fetch(): String
}
class NetworkSource : DataSource {
override fun fetch() = "raw-data"
}
fun main() {
println(NetworkSource().fetch())
}Dekorator logowania
Dekorator deleguje do opakowanego źródła i dodaje logowanie wokół wywołania, które go interesuje.
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())
}Dekorator buforowania
Inny dekorator buforuje pierwszy wynik, dzięki czemu kolejne wywołania pomijają źródłową implementację.
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
}Łączenie dekoratorów
Ponieważ każdy dekorator sam jest obiektem DataSource, można je łączyć. Kolejność ma znaczenie: zewnętrzny opakowuje wewnętrzny.
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())
}Dekorator walidujący
Dekoratory mogą również sprawdzać dane wejściowe. Tutaj dekorator przeprowadza walidację przed delegowaniem do właściwego wykonawcy.
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"))
}Opakowanie kolekcji tylko do odczytu
Delegowanie ułatwia tworzenie opakowań adaptujących. Tutaj opakowujemy listę i dodajemy własną metodę podsumowania, przekazując dalej wszystkie operacje listy.
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())
}Zliczanie wywołań
Dekorator może w przejrzysty sposób śledzić metryki, co przydaje się do monitorowania bez ingerowania w rzeczywistą implementację.
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)
}Dlaczego tutaj wygrywa delegowanie
Budowanie dekoratorów za pomocą dziedziczenia wymuszałoby oznaczenie klasy bazowej jako open i wiązałoby każdy dekorator z konkretną klasą. Delegowanie zależy tylko od interfejsu, dlatego dekoratory pozostają luźno powiązane i można je łatwo komponować.
Lista kontrolna wzorca
Aby zbudować dekorator oparty na delegowaniu:
- Przyjmij opakowany obiekt jako
private val - Deleguj interfejs za pomocą
by - Zastępuj tylko rozszerzane składowe
- Wewnątrz zastąpionej składowej wywołuj obiekt wewnętrzny
Łączymy wszystko
Dekoratory, adaptery i proxy wynikają naturalnie z delegowania klas. W połączeniu z małymi interfejsami pozwalają budować elastyczne, warstwowe systemy, które łatwo testować i rozszerzać.
Szybkie sprawdzenie
Sprawdź swoją wiedzę na temat praktycznych wzorców delegowania.
Podsumowanie
Zbudowano praktyczne dekoratory z użyciem delegowania:
- Opakowania do logowania, buforowania, walidacji i zliczania
- Łączenie dekoratorów, ponieważ każdy implementuje ten sam interfejs
- Zastępowanie tylko rozszerzanych składowych i przekazywanie dalej pozostałych
To kończy kurs delegowania klas.
Często zadawane pytania
Czy lekcja „Praktyczne wzorce” jest bezpłatna?
Tak — pełny tekst „Praktyczne wzorce” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Praktyczne wzorce”?
Dekoratory z delegowaniem Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?
Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Praktyczne wzorce”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?
Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.