Pola Dekorator
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Swift di Coddy. Pelajaran 47 dari 57.
Pola decorator menambahkan perilaku pada sebuah object dengan membungkusnya dalam object lain yang memiliki protokol yang sama. Wrapper meneruskan pemanggilan ke object yang dibungkus dan menambahkan bagiannya sendiri sebelum atau sesudahnya:
protocol Coffee {
func cost() -> Int
func label() -> String
}
struct Espresso: Coffee {
func cost() -> Int { 200 }
func label() -> String { "espresso" }
}
struct WithMilk: Coffee {
let base: any Coffee
func cost() -> Int { base.cost() + 50 }
func label() -> String { base.label() + " + milk" }
}
let drink = WithMilk(base: Espresso())
print(drink.label())
print(drink.cost())Output:
espresso + milk
250Karena decorator itu sendiri adalah Coffee, decorator dapat membungkus satu sama lain dalam kombinasi dan urutan apa pun, tanpa perlu membuat subclass untuk setiap kombinasi:
protocol Coffee { func cost() -> Int; func label() -> String }
struct Espresso: Coffee { func cost() -> Int { 200 }; func label() -> String { "espresso" } }
struct WithMilk: Coffee {
let base: any Coffee
func cost() -> Int { base.cost() + 50 }
func label() -> String { base.label() + " + milk" }
}
struct WithSyrup: Coffee {
let base: any Coffee
func cost() -> Int { base.cost() + 30 }
func label() -> String { base.label() + " + syrup" }
}
let fancy = WithSyrup(base: WithMilk(base: WithMilk(base: Espresso())))
print(fancy.label())
print(fancy.cost())Output:
espresso + milk + milk + syrup
330Decorator cocok untuk menambahkan hal lintas komponen seperti pencatatan log, caching, atau validasi di sekitar komponen yang sudah ada, tanpa mengubah komponen tersebut:
protocol DataSource { func fetch(_ id: Int) -> String }
struct Database: DataSource { func fetch(_ id: Int) -> String { "row \(id)" } }
struct Logged: DataSource {
let inner: any DataSource
func fetch(_ id: Int) -> String {
print("fetching \(id)")
return inner.fetch(id)
}
}
let source: any DataSource = Logged(inner: Database())
print(source.fetch(7))Output:
fetching 7
row 7Kode yang menggunakan object hanya melihat protokol, jadi tidak bisa membedakan object yang dihias dari object biasa. Itulah yang membuat pola ini aman untuk ditambahkan nanti.
func printReceipt(_ c: any Coffee) { // berfungsi untuk Espresso dan semua versi yang dibungkus
print("\(c.label()): \(c.cost())")
}Tantangan
MudahPizza dibuat menggunakan decorator. Protocol Pizza memiliki price() dan toppings() (array berisi nama). Base bernilai 800 tanpa topping. Implementasikan decorator Cheese (+150), Olives (+100), dan Double (menggandakan harga semua yang ada di dalamnya dan mengulang topping-nya dua kali). Lengkapi build(_:), yang memulai dari Base dan membungkusnya dengan satu decorator untuk setiap nama sesuai urutan.
Kode yang disediakan membaca baris berisi nama topping yang dipisahkan dengan koma (atau baris kosong), membuat setiap pizza, lalu mencetak 1050: cheese, olives atau 800: plain.
Tulis kodemu di Pizza.swift, Base.swift, Cheese.swift, Olives.swift, Double.swift, dan Functions.swift. main.swift berisi kode input/output yang disediakan dan tidak boleh diedit.
Coba sendiri
// Kode input/output yang disediakan: biarkan apa adanya
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
let names = line.isEmpty ? [] : line.split(separator: ",").map(String.init)
let p = build(names)
let tops = p.toppings()
print("\(p.price()): " + (tops.isEmpty ? "plain" : tops.joined(separator: ", ")))
}
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 ClassMethod dan selfInitializerClass adalah ReferensiUlasan: Kartu Perpustakaan4Enkapsulasi
Kontrol AksesHanya Bisa Dibaca dari LuarMelindungi StateInitializer yang Bisa GagalRangkuman: Rekening Bank7Polimorfisme dan Generik
PolimorfismeKonversi TipeFungsi GenerikTipe GenerikRangkuman: Kalkulator Bentuk2Struct dan Tipe Nilai
StructSemantik NilaiMethod yang Mengubah NilaiStruct atau classRangkuman, Item Inventaris11Proyek: Manajemen Perpustakaan
Buku dan AnggotaPeminjaman BukuLatihan sendiri: Playground Swift