Dekoratör Kalıbı
Coddy'nin Swift Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 47 / 57.
dekoratör deseni, aynı protokole sahip başka bir nesneyle sararak bir nesneye davranış ekler. Sarıcı, çağrıyı sarılan nesneye iletir ve çağrıdan önce veya sonra kendi kısmını ekler:
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())Çıktı:
espresso + milk
250Bir dekoratörün kendisi de bir Coffee olduğundan, dekoratörler her kombinasyon ve sırayla birbirlerini sarabilir; böylece her kombinasyon için bir alt sınıf oluşturmaya gerek kalmaz:
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())Çıktı:
espresso + milk + milk + syrup
330Decorator'lar, değişmeden kalan mevcut bir bileşenin etrafına günlük kaydı, önbelleğe alma veya doğrulama gibi çapraz kesen eklemeler yapmak için uygundur:
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))Çıktı:
fetching 7
row 7Nesneyi kullanan kod yalnızca protokolü görür; bu nedenle dekore edilmiş bir nesneyi sıradan bir nesneden ayırt edemez. Bu da deseni sonradan güvenle eklemeyi mümkün kılar.
func printReceipt(_ c: any Coffee) { // Espresso ve herhangi bir sarmalanmış versiyon için çalışır
print("\(c.label()): \(c.cost())")
}Görev
KolayPizza'lar dekoratörlerle oluşturulur. Pizza protokolünde price() ve toppings() (adlardan oluşan bir dizi) bulunur. Base, üst malzeme olmadan 800'dür. Cheese (+150), Olives (+100) ve Double (içindeki her şeyin fiyatını iki katına çıkarır ve üst malzemelerini iki kez tekrarlar) dekoratörlerini uygulayın. Base'den başlayan ve ad sırasına göre her ad için bir dekoratörle onu saran build(_:) işlevini tamamlayın.
Sağlanan kod, virgülle ayrılmış üst malzeme adlarını (veya boş bir satırı) okur, her pizzayı oluşturur ve 1050: cheese, olives veya 800: plain yazdırır.
Kodunuz Pizza.swift, Base.swift, Cheese.swift, Olives.swift, Double.swift ve Functions.swift dosyalarına yazılmalıdır. main.swift, sağlanan giriş/çıkış kodunu içerir ve düzenlenemez.
Kendin dene
// Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
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: ", ")))
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1Sınıflar ve Nesneler
Dosyalarla ÇalışmaSınıfları TanımlamaMetotlar ve selfBaşlatıcılarSınıflar ReferanstırTekrar - Kütüphane Kartı4Kapsülleme
Erişim DenetimiDışarıdan Salt OkunurDurumu KorumaBaşarısız Olabilen BaşlatıcılarTekrar - Banka Hesabı7Polimorfizm ve Generic'ler
PolimorfizmTür DönüşümüGeneric FonksiyonlarGeneric TürlerTekrar - Şekil Hesaplayıcı2Struct Yapıları ve Değer Türleri
Struct YapılarıDeğer SemantiğiDeğiştirici MetotlarStruct mı Class mıTekrar - Envanter Öğesi5Kalıtım
Alt sınıflarMetotları Geçersiz KılmaBaşlatıcılar ve superfinal ve HiyerarşilerTekrar - Çalışan Hiyerarşisi11Proje: Kütüphane Yönetimi
Kitaplar ve ÜyelerKitap Ödünç AlmaKendi başına pratik yap: Swift playground