Dekoratör Kalıbı
Coddy'nin Python Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 51 / 64.
Decorator Pattern, nesnelerin yapısını değiştirmeden onlara dinamik olarak yeni işlevler ekler. Davranışlarını genişletmek için nesneleri sarar.
İşte basit bir kahve örneği:
class Coffee:
def cost(self):
return 5
def description(self):
return "Simple coffee"Kahveye özellikler ekleyen dekoratörler oluşturun:
class MilkDecorator:
def __init__(self, coffee):
self.coffee = coffee
def cost(self):
return self.coffee.cost() + 2
def description(self):
return self.coffee.description() + " + Milk"
class SugarDecorator:
def __init__(self, coffee):
self.coffee = coffee
def cost(self):
return self.coffee.cost() + 1
def description(self):
return self.coffee.description() + " + Sugar"Her bir dekoratör başka bir nesneyi sarmalar ve kendi işlevselliğini ekler.
Özelleştirilmiş kahve oluşturmak için dekoratörleri kullanın:
# Temel kahve ile başla
my_coffee = Coffee()
print(f"{my_coffee.description()}: ${my_coffee.cost()}")
# Süt ekle
my_coffee = MilkDecorator(my_coffee)
print(f"{my_coffee.description()}: ${my_coffee.cost()}")
# Şeker ekle
my_coffee = SugarDecorator(my_coffee)
print(f"{my_coffee.description()}: ${my_coffee.cost()}")Metin biçimlendirmeli başka bir örnek oluşturun:
class Text:
def __init__(self, content):
self.content = content
def render(self):
return self.content
class BoldDecorator:
def __init__(self, text):
self.text = text
def render(self):
return f"<b>{self.text.render()}</b>"
class ItalicDecorator:
def __init__(self, text):
self.text = text
def render(self):
return f"<i>{self.text.render()}</i>"
# Biçimlendirilmiş metni adım adım oluşturun
message = Text("Hello World")
message = BoldDecorator(message)
message = ItalicDecorator(message)
print(message.render())Çıktı:
Simple coffee: $5
Simple coffee + Milk: $7
Simple coffee + Milk + Sugar: $8
<i><b>Hello World</b></i>Temel Nokta: Decorator Pattern, özgün nesneyi değiştirmeden yeni davranış eklemek için nesneleri sarar. Her dekoratör, sarılmış nesneye bir başvuru tutar ve kendi işlevselliğini ekler. Bu, çok sayıda alt sınıf oluşturmadan esnek özellik kombinasyonları için birden fazla dekoratörü birleştirmenize olanak tanır.
Görev
OrtaBu meydan okumada, bir kahve dükkânı için esnek bir kahve sipariş sistemi oluşturmak üzere Dekoratör tasarım desenini uygulayacaksınız. Dekoratör deseni, aynı sınıftaki diğer nesnelerin davranışını etkilemeden, davranışın tek tek nesnelere dinamik olarak eklenmesine olanak tanır.
Şunları yapması gereken bir kahve dükkânı sistemi oluşturuyorsunuz:
- Çeşitli içecek türleri sunmak (Espresso, Dark Roast, House Blend, Decaf)
- Müşterilerin içeceklerine çeşitli ek malzemeler katmasına olanak tanımak (Milk, Mocha, Soy, Whipped Cream)
- Eklenen malzemelerle birlikte içeceklerin maliyetini hesaplamak
beverage.pydosyasındaki soyutBeveragesınıfını ve somut uygulamalarını tamamlamakcondiment_decorator.pydosyasındaki soyutCondimentDecoratorsınıfını ve somut dekoratörleri uygulamak- Uygulamanızı doğrulamak için
driver.pydosyasında test senaryoları uygulamak
Kendin dene
# Gerekli tüm sınıfları içe aktar
from beverage import Espresso, HouseBlend, DarkRoast, Decaf
from condiment_decorator import Milk, Mocha, Soy, Whip
# Kapsamlı test senaryosu işleyicisi
test_case = input()
if test_case == "basic_beverage_test":
# Temel içecek işlevselliğini test et
espresso = Espresso()
print(f"Description: {espresso.get_description()}")
print(f"Cost: ${espresso.cost():.2f}")
elif test_case == "all_beverages_test":
# Tüm içecek türlerini test et
beverages = [Espresso(), HouseBlend(), DarkRoast(), Decaf()]
for beverage in beverages:
print(f"{beverage.get_description()}: ${beverage.cost():.2f}")
elif test_case == "single_condiment_test":
# Tekli garnitür süslemesini test et
espresso = Espresso()
espresso_with_milk = Milk(espresso)
print(f"Description: {espresso_with_milk.get_description()}")
print(f"Cost: ${espresso_with_milk.cost():.2f}")
elif test_case == "multiple_condiments_test":
# Çoklu garnitür süslemelerini test et
house_blend = HouseBlend()
decorated_coffee = Mocha(Soy(Whip(house_blend)))
print(f"Description: {decorated_coffee.get_description()}")
print(f"Cost: ${decorated_coffee.cost():.2f}")
elif test_case == "all_condiments_test":
# Bir içecek üzerindeki tüm garnitürleri test et
dark_roast = DarkRoast()
fully_loaded = Milk(Mocha(Soy(Whip(dark_roast))))
print(f"Description: {fully_loaded.get_description()}")
print(f"Cost: ${fully_loaded.cost():.2f}")
elif test_case == "cost_calculation_test":
# Farklı kombinasyonlar için maliyet hesaplamalarını test et
espresso = Espresso()
# Tekli eklemeler
with_milk = Milk(espresso)
with_mocha = Mocha(espresso)
print(f"Espresso: ${espresso.cost():.2f}")
print(f"Espresso + Milk: ${with_milk.cost():.2f}")
print(f"Espresso + Mocha: ${with_mocha.cost():.2f}")
elif test_case == "decoration_order_test":
# Süsleme sırasının nihai sonucu etkilemediğini test et
decaf = Decaf()
order1 = Milk(Mocha(decaf))
order2 = Mocha(Milk(decaf))
print(f"Order 1 - {order1.get_description()}: ${order1.cost():.2f}")
print(f"Order 2 - {order2.get_description()}: ${order2.cost():.2f}")
print(f"Same cost: {order1.cost() == order2.cost()}")
elif test_case == "complex_order_test":
# Karmaşık içecek siparişlerini test et
orders = [
Mocha(Whip(Espresso())),
Soy(Milk(HouseBlend())),
Whip(Mocha(Soy(DarkRoast()))),
Milk(Decaf())
]
for i, order in enumerate(orders, 1):
print(f"Order {i}: {order.get_description()}")
print(f"Cost: ${order.cost():.2f}")
print("---")
elif test_case == "double_condiment_test":
# Aynı garnitürün birden fazla kez eklenmesini test et
espresso = Espresso()
double_mocha = Mocha(Mocha(espresso))
print(f"Description: {double_mocha.get_description()}")
print(f"Cost: ${double_mocha.cost():.2f}")
elif test_case == "beverage_comparison_test":
# Aynı garnitürlere sahip farklı içeceklerin maliyetlerini karşılaştır
base_beverages = [Espresso(), HouseBlend(), DarkRoast(), Decaf()]
print("All beverages with Milk + Mocha:")
for beverage in base_beverages:
decorated = Milk(Mocha(beverage))
print(f"{decorated.get_description()}: ${decorated.cost():.2f}")
elif test_case == "condiment_cost_test":
# Bireysel garnitür maliyetlerini test et
espresso = Espresso()
base_cost = espresso.cost()
condiments = [
("Milk", Milk(espresso)),
("Mocha", Mocha(espresso)),
("Soy", Soy(espresso)),
("Whip", Whip(espresso))
]
for name, decorated in condiments:
additional_cost = decorated.cost() - base_cost
print(f"{name} adds: ${additional_cost:.2f}")
elif test_case == "cheapest_most_expensive_test":
# En ucuz ve en pahalı temel içecekleri bul
beverages = [
("Espresso", Espresso()),
("House Blend", HouseBlend()),
("Dark Roast", DarkRoast()),
("Decaf", Decaf())
]
beverages.sort(key=lambda x: x[1].cost())
print(f"Cheapest: {beverages[0][0]} - ${beverages[0][1].cost():.2f}")
print(f"Most Expensive: {beverages[-1][0]} - ${beverages[-1][1].cost():.2f}")
elif test_case == "nested_decoration_test":
# Derinlemesine iç içe geçmiş süslemeleri test et
beverage = HouseBlend()
# 5 katman süsleme ekle
decorated = Whip(Soy(Mocha(Milk(Whip(beverage)))))
print(f"Description: {decorated.get_description()}")
print(f"Cost: ${decorated.cost():.2f}")
# Garnitür sayısını say
description = decorated.get_description()
condiment_count = description.count(" + ")
print(f"Number of condiments: {condiment_count}")
elif test_case == "cost_breakdown_test":
# Detaylı maliyet dökümü
dark_roast = DarkRoast()
print(f"Base Dark Roast: ${dark_roast.cost():.2f}")
with_soy = Soy(dark_roast)
print(f"+ Soy: ${with_soy.cost():.2f}")
with_mocha = Mocha(with_soy)
print(f"+ Mocha: ${with_mocha.cost():.2f}")
with_whip = Whip(with_mocha)
print(f"+ Whip: ${with_whip.cost():.2f}")
final_cost = with_whip.cost()
print(f"Final total: ${final_cost:.2f}")
elif test_case == "description_format_test":
# Açıklama biçimlendirme tutarlılığını test et
espresso = Espresso()
test_combinations = [
Milk(espresso),
Mocha(Milk(espresso)),
Whip(Mocha(Milk(espresso))),
Soy(Whip(Mocha(Milk(espresso))))
]
for combo in test_combinations:
description = combo.get_description()
print(f"Description: '{description}'")
# Açıklamanın temel içecek adıyla başlayıp başlamadığını kontrol et
starts_correctly = description.startswith("Espresso")
print(f"Starts with base name: {starts_correctly}")
print("---")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
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesnelerself ParametresiMetotlarÖzniteliklerYapıcı Metot (__init__)Özet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımsuper() FonksiyonuMetot Geçersiz KılmaÇoklu KalıtımMetot Çözümleme SırasıÖzet - Çalışan Hiyerarşisi7Özel Metotlar
Sihirli Metotlara GirişOperatör Aşırı YüklemeKapsayıcı Sihirli MetotlarıÖzet - Özel Liste10Tasarım Kalıpları Bölüm 1
Tasarım kalıplarına girişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı13Final Meydan Okumaları
E-öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi5Çok Biçimlilik (Polymorphism)
Metot Geçersiz Kılmaya Yeniden BakışDuck TypingSoyut Sınıflar ve MetotlarArayüz TasarımıÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon ve KalıtımMixinsStatik ve Sınıf MetotlarıSınıf DekoratörleriBağlam Yöneticileri11Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıKendi başına pratik yap: Online Python derleyicisi