Pola Decorator
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Kotlin di Coddy. Pelajaran 47 dari 57.
Pola decorator menambahkan perilaku pada object dengan membungkusnya dalam object lain yang memiliki antarmuka yang sama. Decorator meneruskan panggilan ke object yang dibungkusnya dan menambahkan bagiannya sendiri, sehingga decorator dapat ditumpuk:
interface Coffee {
fun cost(): Int
fun description(): String
}
class Espresso : Coffee {
override fun cost() = 200
override fun description() = "espresso"
}
class Milk(private val inner: Coffee) : Coffee {
override fun cost() = inner.cost() + 50
override fun description() = inner.description() + ", milk"
}
class Syrup(private val inner: Coffee) : Coffee {
override fun cost() = inner.cost() + 30
override fun description() = inner.description() + ", syrup"
}Di dalam main:
val order = Syrup(Milk(Milk(Espresso())))
println("${order.description()}: ${order.cost()}")Output:
espresso, milk, milk, syrup: 330Saat decorator mengubah hasil, urutannya penting: masing-masing bekerja pada hasil yang dikembalikan oleh object di dalamnya:
interface Text {
fun render(): String
}
class Word(private val w: String) : Text {
override fun render() = w
}
class Bracket(private val inner: Text) : Text {
override fun render() = "[" + inner.render() + "]"
}
class Twice(private val inner: Text) : Text {
override fun render() = inner.render() + inner.render()
}Di dalam main:
println(Twice(Bracket(Word("hi"))).render())
println(Bracket(Twice(Word("hi"))).render())Output:
[hi][hi]
[hihi]Dengan by, decorator hanya menulis member yang diubahnya dan meneruskan sisanya secara otomatis:
interface Source {
fun read(): String
fun name(): String
}
class FileSource(private val content: String) : Source {
override fun read() = content
override fun name() = "notes.txt"
}
class Censored(private val inner: Source, private val word: String) : Source by inner {
override fun read() = inner.read().replace(word, "***")
}Di dalam main:
val src = Censored(FileSource("the secret plan"), "secret")
println("${src.name()}: ${src.read()}")Output:
notes.txt: the *** planDekorator digabungkan saat program berjalan, misalnya berdasarkan pilihan pelanggan, sedangkan subclass menetapkan satu kombinasi saat kode ditulis. Tiga tambahan sebagai subclass memerlukan satu class untuk setiap kombinasi. Sebagai dekorator, fold menyusunnya dari sebuah list:
interface Coffee {
fun cost(): Int
}
class Espresso : Coffee {
override fun cost() = 200
}
class Extra(private val inner: Coffee, private val price: Int) : Coffee {
override fun cost() = inner.cost() + price
}Di dalam main:
val prices = mapOf("milk" to 50, "syrup" to 30, "cream" to 70)
val choices = listOf("milk", "cream", "milk")
val coffee = choices.fold<String, Coffee>(Espresso()) { c, extra -> Extra(c, prices.getValue(extra)) }
println(coffee.cost())Output:
370Tantangan
MudahPizza dibuat menggunakan decorator dari interface yang disediakan, Pizza (dengan price() dan toppings()). Tulis Base (800, tanpa topping) dan decorator Cheese (+150, menambahkan cheese), Olives (+100, menambahkan olives) dan DoubleUp, yang menggandakan harga semua yang ada di dalamnya dan mengulang toppingnya dua kali. Lalu tulis build(names), yang memulai dari Base dan membungkusnya dengan satu decorator untuk setiap nama, sesuai urutan (cheese, olives atau double).
Kode yang disediakan membaca baris berisi nama yang dipisahkan koma, atau plain, membuat setiap pizza dan mencetak 1050: cheese, olives atau 800: plain.
Tulis kodemu di Base.kt, Cheese.kt, Olives.kt, DoubleUp.kt, Build.kt dan Pizza.kt. Main.kt berisi kode input/output yang disediakan dan tidak dapat diedit.
Coba sendiri
fun main() {
// Kode input/output yang disediakan: biarkan apa adanya
val input = generateSequence(::readLine).toList()
for (line in input) {
val names = if (line == "plain") listOf() else line.split(",")
val pizza = build(names)
val toppings = pizza.toppings()
println("${pizza.price()}: " + if (toppings.isEmpty()) "plain" else toppings.joinToString(", "))
}
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1class dan object
Bekerja dengan fileMendefinisikan classKonstruktor utamaBlok init dan validasiKonstruktor sekunderRingkasan: Kartu Perpustakaan2property dan Enkapsulasi
Accessor KustomModifier VisibilitasSetter Privatlazy dan lateinitRingkasan: Rekening Bank5Interface
Mendeklarasikan Interfacemethod DefaultBeberapa InterfaceInterface sebagai TipeUlasan: Metode Pembayaran11Proyek: Pengelolaan Perpustakaan
Buku dan AnggotaPeminjaman BukuLatihan sendiri: Playground Kotlin