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 Deseni (Dekoratör Deseni), nesneleri dekoratör adı verilen özel sarmalayıcı nesnelerin içine sararak onlara dinamik olarak yeni davranışlar eklemenize olanak tanıyan yapısal bir tasarım desenidir. Derleme zamanında davranış ekleyen kalıtımın aksine, dekoratörler çalışma zamanında davranış ekler.

Bir kahve dükkanı hayal edin. Temel bir kahve ile başlarsınız, ardından süt, şeker veya krem şanti gibi ekstralar eklersiniz.

Her ekleme orijinal kahveyi sarmalar ve onun açıklamasına ve maliyetine ekleme yapar. Temel nokta, hem temel kahvenin hem de dekoratörlerin aynı arayüzü paylaşması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 sarmalar:

<?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, bir zincir oluşturacak şekilde önceki nesneyi sarmalar. Bu desen, her olası kombinasyon için bir sınıf oluşturmadan, davranışları herhangi bir sırada ve miktarda birleştirmenize olanak tanır. Çift süt mü lazım? Sadece iki kez sarmalayın.

challenge icon

Görev

Kolay

Decorator Desenini kullanarak bir pizza sipariş sistemi oluşturalım. Temel bir pizza ile başlayacak ve dinamik olarak malzemeler ekleyeceksiniz — her malzeme pizzayı sarmalar ve dersteki kahve örneğinde olduğu gibi açıklamasına ve fiyatına ekleme yapar.

Kodunuzu dört dosya halinde düzenleyeceksiniz:

  • Pizza.php — Tüm pizzalar ve malzemeler için sözleşmeyi belirleyen bir Pizza arayüzü (interface) tanımlayın. İki yöntemi olmalıdır: getDescription(): string ve getPrice(): float.
  • BasePizza.php — Pizza arayüzünü dahil edin ve onu uygulayan (implement) bir MargheritaPizza sınıfı oluşturun. Bu, "Margherita" açıklamasına ve 8.00 fiyatına sahip temel pizzanızdır.
  • Toppings.php — Pizza arayüzünü dahil edin ve onu uygulayan üç dekoratör sınıfı oluşturun. Her dekoratör bir Pizza nesnesini sarmalar (bunu yapıcıda/constructor kabul edin) 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 edin. Bir girdi alacaksınız: eklenecek malzemelerin virgülle ayrılmış bir listesi (örneğin, "cheese,pepperoni" veya "mushroom,cheese,cheese").

    Bir MargheritaPizza ile başlayın. Girdideki her malzeme için pizzanızı uygun dekoratörle sarmalayın:

    • "cheese", CheeseTopping ile sarmalar
    • "pepperoni", PepperoniTopping ile sarmalar
    • "mushroom", MushroomTopping ile sarmalar

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

    [description] = $[price]

    Fiyatı iki ondalık basamak olacak şekilde formatlayın.

Aynı malzemenin birden fazla kez nasıl uygulanabildiğine dikkat edin — çift peynir sipariş etmek, sadece CheeseTopping ile iki kez sarmalamak anlamına gelir. Bu esneklik, Decorator Deseninin gücüdür!

Kopya kağıdı

Decorator Pattern (Dekoratör Deseni), nesneleri çalışma zamanında dekoratör nesneleri içine sararak onlara dinamik olarak davranışlar ekleyen yapısal bir tasarım desenidir.

Hem temel nesne hem de dekoratörler aynı arayüzü uygular:

<?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 tipindeki başka bir nesneyi 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;
    }
}

Davranışları birleştirmek için dekoratörleri zincirleyin:

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

echo $coffee->getDescription() . " = $" . $coffee->getCost();
// Çıktı: Simple Coffee, Milk, Sugar = $2.75

Dekoratörler, her kombinasyon için yeni sınıflar oluşturmaya gerek kalmadan birden fazla kez ve herhangi bir sırada uygulanabilir.

Kendin dene

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

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

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

// TODO: Her bir malzeme üzerinden döngü kurun ve pizzayı uygun dekoratör ile sarmalayın
// - "cheese" -> CheeseTopping ile sarmala
// - "pepperoni" -> PepperoniTopping ile sarmala
// - "mushroom" -> MushroomTopping ile sarmala

// TODO: Sonucu şu formatta yazdırın: [description] = $[price]
// number_format() kullanarak fiyatı 2 ondalık basamak olacak şekilde biçimlendirin

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