Menu
Coddy logo textTech

Dekoratör Kalıbı

Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 77 / 91.

Decorator Pattern, nesneleri dekoratör adı verilen özel sarmalayıcı nesnelerle sararak nesnelere dinamik olarak yeni davranışlar eklemenizi sağlayan yapısal bir tasarım desenidir. Derleme zamanında davranış ekleyen kalıtımın aksine, dekoratörler davranışı çalışma zamanında ekler.

Bir kahve dükkânı hayal et. Basit bir kahveyle başlarsın, ardından süt, şeker veya krem şanti gibi ekstralar eklersin.

Her ekleme, orijinal kahveyi sarar ve açıklamasına ve maliyetine ekleme yapar. Temel içeceğin ve dekoratörlerin aynı arayüzü paylaşması temel içgörüdür.

<?php
interface Coffee {
    public function getDescription(): string;
    public function getCost(): float;
}

class SimpleCoffee implements Coffee {
    public function getDescription(): string {
        return "Simple Coffee";
    }
    
    public function getCost(): float {
        return 2.00;
    }
}

Dekoratörler aynı arayüzü uygular ve başka bir Coffee nesnesini sarar:

<?php
class MilkDecorator implements Coffee {
    public function __construct(private Coffee $coffee) {}
    
    public function getDescription(): string {
        return $this->coffee->getDescription() . ", Milk";
    }
    
    public function getCost(): float {
        return $this->coffee->getCost() + 0.50;
    }
}

class SugarDecorator implements Coffee {
    public function __construct(private Coffee $coffee) {}
    
    public function getDescription(): string {
        return $this->coffee->getDescription() . ", Sugar";
    }
    
    public function getCost(): float {
        return $this->coffee->getCost() + 0.25;
    }
}

$coffee = new SimpleCoffee();
$coffee = new MilkDecorator($coffee);
$coffee = new SugarDecorator($coffee);

echo $coffee->getDescription() . " = $" . $coffee->getCost();

Çıktı:

Simple Coffee, Milk, Sugar = $2.75

Her dekoratör, önceki nesneyi sararak bir zincir oluşturur. Bu desen, olası her kombinasyon için bir sınıf oluşturmadan davranışları istediğiniz sırada ve miktarda birleştirmenizi sağlar. Çift süt mü gerekiyor? Sadece iki kez sarın.

challenge icon

Görev

Kolay

Decorator Pattern'ı kullanarak bir pizza sipariş sistemi oluşturalım. Temel bir pizzayla başlayacak ve malzemeleri dinamik olarak ekleyeceksin: her malzeme pizzayı sarar ve derse ait kahve örneğinde olduğu gibi açıklamasına ve fiyatına ekleme yapar.

Kodunu dört dosyaya dağıtacaksın:

  • Pizza.php: Tüm pizzalar ve malzemeler için sözleşmeyi tanımlayan bir Pizza arayüzü tanımla. İki yöntemi olmalı: getDescription(): string ve getPrice(): float.
  • BasePizza.php: Pizza arayüzünü dahil et ve bunu uygulayan bir MargheritaPizza sınıfı oluştur. Bu, açıklaması "Margherita" ve fiyatı 8.00 olan temel pizzandır.
  • Toppings.php: Pizza arayüzünü dahil et ve bunu uygulayan üç dekoratör sınıfı oluştur. Her dekoratör bir Pizza nesnesini sarar (nesneyi kurucuda kabul eder) ve hem açıklamayı hem de fiyatı geliştirir:
    • CheeseTopping: Açıklamaya ", Extra Cheese" ve fiyata 1.50 ekler
    • PepperoniTopping: Açıklamaya ", Pepperoni" ve fiyata 2.00 ekler
    • MushroomTopping: Açıklamaya ", Mushrooms" ve fiyata 1.25 ekler
  • main.php: BasePizza ve Toppings dosyalarını dahil et. Eklenecek malzemelerin virgülle ayrılmış bir listesini girdi olarak alacaksın (örneğin, "cheese,pepperoni" veya "mushroom,cheese,cheese").

    Bir MargheritaPizza ile başla. Girdideki her malzeme için pizzanı uygun dekoratörle sar:

    • "cheese", CheeseTopping ile sarılır
    • "pepperoni", PepperoniTopping ile sarılır
    • "mushroom", MushroomTopping ile sarılır

    Tüm malzemeleri uyguladıktan sonra son pizzanın açıklamasını ve fiyatını şu biçimde yazdır:

    [description] = $[price]

    Fiyatı iki ondalık basamağa biçimlendir.

Aynı malzemenin birden fazla kez uygulanabildiğine dikkat et: iki kat peynir sipariş etmek, yalnızca CheeseTopping ile iki kez sarmak anlamına gelir. Decorator Pattern'ın gücü işte bu esnekliktir!

Kendin dene

<?php
require_once 'BasePizza.php';
require_once 'Toppings.php';

// Girdiyi oku - virgülle ayrılmış topping listesi
$input = trim(fgets(STDIN));
$toppings = explode(',', $input);

// Temel bir MargheritaPizza ile başla
$pizza = new MargheritaPizza();

// TODO: Her topping üzerinden döngü yap ve pizzayı uygun decorator ile sar
// - "cheese" -> CheeseTopping ile sar
// - "pepperoni" -> PepperoniTopping ile sar
// - "mushroom" -> MushroomTopping ile sar

// TODO: Sonucu şu formatta yazdır: [description] = $[price]
// Fiyatı number_format() kullanarak 2 ondalık basamağa biçimlendir

?>
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

Kendi başına pratik yap: Online PHP derleyicisi