Menu
Coddy logo textTech

Dekoratör Kalıbı

Coddy'nin Dart Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 96 / 110.

Decorator deseni, nesneleri dekoratör adı verilen özel nesnelerle sarmalayarak onlara dinamik olarak yeni davranışlar eklemenize olanak tanır. Derleme zamanında davranış ekleyen kalıtımın aksine, dekoratörler orijinal sınıfı değiştirmeden çalışma zamanında ek sorumluluklar yükler.

Temel fikir, hem orijinal nesnenin hem de dekoratörlerin aynı arayüzü uygulamasıdır.

Bir dekoratör orijinal nesneyi sarmalar, ona delege eder ve öncesinde veya sonrasında kendi davranışını ekler:

abstract class Coffee {
  String getDescription();
  double getCost();
}

class SimpleCoffee implements Coffee {
  @override
  String getDescription() => 'Simple Coffee';

  @override
  double getCost() => 2.0;
}

class MilkDecorator implements Coffee {
  final Coffee _coffee;
  MilkDecorator(this._coffee);

  @override
  String getDescription() => '${_coffee.getDescription()}, Milk';

  @override
  double getCost() => _coffee.getCost() + 0.5;
}

class SugarDecorator implements Coffee {
  final Coffee _coffee;
  SugarDecorator(this._coffee);

  @override
  String getDescription() => '${_coffee.getDescription()}, Sugar';

  @override
  double getCost() => _coffee.getCost() + 0.2;
}

void main() {
  Coffee coffee = SimpleCoffee();
  coffee = MilkDecorator(coffee);
  coffee = SugarDecorator(coffee);

  print(coffee.getDescription());  // Simple Coffee, Milk, Sugar
  print(coffee.getCost());         // 2.7
}

Her dekoratör, bir önceki nesneyi sarmalar ve onu geliştirir. Her olası kombinasyon için bir alt sınıf (subclass) oluşturmadan esnek bir davranış yaratarak, birden fazla dekoratörü herhangi bir kombinasyonda üst üste ekleyebilirsiniz. Bu desen, aynı sınıfa ait diğer nesneleri etkilemeden nesnelere özellikler eklemeniz gerektiğinde idealdir.

challenge icon

Görev

Kolay

Decorator desenini kullanarak bir pizza sipariş sistemi oluşturalım! Her bir malzemenin bir önceki öğeyi sarmaladığı ve hem açıklamaya hem de fiyata ekleme yaptığı, çeşitli malzemelerle geliştirilebilen temel bir pizza oluşturacaksınız.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • pizza.dart: Bu dosya pizza arayüzünüzü ve tüm dekoratör sınıflarını içerir. İki yöntem tanımlayan bir Pizza soyut sınıfı ile başlayın: String getDescription() ve double getPrice(). Ardından Pizza arayüzünü uygulayan bir PlainPizza sınıfı oluşturun - bu sınıf açıklama olarak Plain Pizza döndürür ve maliyeti 8.0'dır. Şimdi her biri bir Pizza nesnesini sarmalayan ve onu geliştiren üç dekoratör sınıfı oluşturun:
    • CheeseDecorator - açıklamaya , Cheese ve fiyata 1.5 ekler
    • PepperoniDecorator - açıklamaya , Pepperoni ve fiyata 2.0 ekler
    • MushroomDecorator - açıklamaya , Mushrooms ve fiyata 1.25 ekler
    Her dekoratör Pizza arayüzünü uygulamalı, yapıcı metodunda (constructor) bir Pizza kabul etmeli ve kendi katkısını eklemeden önce sarmalanmış pizzaya delege etmelidir.
  • main.dart: Pizza dosyanızı içe aktarın ve dekoratörlerin özelleştirilmiş bir sipariş oluşturmak için nasıl üst üste bindiğini gösterin. Bir PlainPizza ile başlayın, ardından onu CheeseDecorator ile sarmalayın, sonra bunu PepperoniDecorator ile sarmalayın ve son olarak her şeyi MushroomDecorator ile sarmalayın. Nihai pizzanın açıklamasını yazdırın, ardından Total: $ ve sonrasında fiyatı yazdırın.

Her dekoratörün bir öncekinin üzerine nasıl inşa edildiğine dikkat edin - basit, tek sorumluluklu dekoratörleri üst üste koyarak tam donanımlı bir pizza oluşturuyorsunuz!

Beklenen çıktı:

Plain Pizza, Cheese, Pepperoni, Mushrooms
Total: $12.75

Kopya kağıdı

Decorator deseni, nesneleri dekoratör nesneleriyle sarmalayarak onlara dinamik olarak yeni davranışlar ekler. Hem orijinal nesne hem de dekoratörler aynı arayüzü uygular.

Temel bileşenler:

  • Ortak metotları tanımlayan soyut bir sınıf veya arayüz
  • Temel işlevselliği uygulayan somut bir sınıf
  • Orijinal nesneyi sarmalayan ve onu geliştiren dekoratör sınıfları

Her dekoratör:

  • Dekore ettiği nesneyle aynı arayüzü uygular
  • Sarmalanmış nesneye bir referans tutar
  • Çağrıları sarmalanmış nesneye iletir
  • İletimden önce veya sonra kendi davranışını ekler
abstract class Coffee {
  String getDescription();
  double getCost();
}

class SimpleCoffee implements Coffee {
  @override
  String getDescription() => 'Simple Coffee';

  @override
  double getCost() => 2.0;
}

class MilkDecorator implements Coffee {
  final Coffee _coffee;
  MilkDecorator(this._coffee);

  @override
  String getDescription() => '${_coffee.getDescription()}, Milk';

  @override
  double getCost() => _coffee.getCost() + 0.5;
}

// Birden fazla dekoratörü üst üste ekleyin
Coffee coffee = SimpleCoffee();
coffee = MilkDecorator(coffee);
coffee = SugarDecorator(coffee);

Dekoratörler herhangi bir kombinasyonda üst üste eklenebilir, bu da her olası kombinasyon için alt sınıflar oluşturmaya gerek kalmadan esnek bir davranış sağlar.

Kendin dene

import 'pizza.dart';

void main() {
  // TODO: Bir PlainPizza oluşturun
  
  // TODO: Onu CheeseDecorator ile sarmalayın
  
  // TODO: Onu PepperoniDecorator ile sarmalayın
  
  // TODO: Her şeyi MushroomDecorator ile sarmalayın
  
  // TODO: Nihai pizzanın açıklamasını yazdırın
  
  // TODO: "Total: $" ve ardından fiyatı yazdırın
}
quiz iconKendini test et

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