Sobes.tech
Middle

Πώς λειτουργεί ένας διακοσμητής στο PHP;

sobes.tech AI

Απάντηση από AI

Το μοτίβο "Διακοσμητής" προσθέτει δυναμικά νέα συμπεριφορά σε ένα υπάρχον αντικείμενο, περιτυλίγοντάς το σε ένα άλλο αντικείμενο που ονομάζεται διακοσμητής.

  • Συστατικά:

    • Διασύνδεση (Component): Ανακοινώνει κοινές μεθόδους για το αρχικό αντικείμενο και τους διακοσμητές του.
    • Συγκεκριμένο Συστατικό (Concrete Component): Το βασικό αντικείμενο που πρέπει να διακοσμηθεί.
    • Βασικός Διακοσμητής (Decorator): Μια αφηρημένη κλάση ή διασύνδεση που περιέχει μια αναφορά σε ένα αντικείμενο διασύνδεσης (Component) και υλοποιεί τις μεθόδους του, συνήθως αναθέτοντας την κλήση σε αυτό το αντικείμενο.
    • Συγκεκριμένοι Διακοσμητές (Concrete Decorators): Υλοποιούν νέες δυνατότητες, συμπληρώνοντας ή τροποποιώντας τη συμπεριφορά του βασικού συστατικού.
  • Λειτουργία:

    • Ο διακοσμητής περιέχει μια αναφορά στο αντικείμενο που διακοσμεί (σύνθεση).
    • Ο διακοσμητής έχει την ίδια διασύνδεση, με το διακοσμημένο αντικείμενο.
    • Κατά την κλήση μιας μεθόδου στον διακοσμητή, είτε εκτελεί επιπλέον λογική πριν ή μετά την κλήση της αντίστοιχης μεθόδου στο διακοσμημένο αντικείμενο, είτε το αντικαθιστά πλήρως (αν και αυτό δεν είναι τυπική χρήση).
  • Πλεονεκτήματα:

    • Επιτρέπει την προσθήκη λειτουργικότητας σε αντικείμενα κατά το χρόνο εκτέλεσης, και όχι με στατική κληρονομικότητα.
    • Αποφεύγει το "σπάσιμο" της ιεραρχίας κλάσεων κατά τον συνδυασμό πολλαπλών διαφορετικών συμπεριφορών.
    • Επιτρέπει τη δημιουργία ευέλικτων συνδυασμών συμπεριφοράς.
  • Παράδειγμα:

<?php

// Διασύνδεση Συστατικού
interface Coffee {
    public function getCost(): float;
    public function getDescription(): string;
}

// Συγκεκριμένο Συστατικό
class SimpleCoffee implements Coffee {
    public function getCost(): float {
        return 5.0;
    }

    public function getDescription(): string {
        return "Απλικός καφές";
    }
}

// Βασικός Διακοσμητής
abstract class CoffeeDecorator implements Coffee {
    protected Coffee $coffee;

    public function __construct(Coffee $coffee) {
        $this->coffee = $coffee;
    }

    public function getCost(): float {
        return $this->coffee->getCost();
    }

    public function getDescription(): string {
        return $this->coffee->getDescription();
    }
}

// Συγκεκριμένος Διακοσμητής: Προσθήκη γάλακτος
class MilkDecorator extends CoffeeDecorator {
    public function getCost(): float {
        return parent::getCost() + 2.0;
    }

    public function getDescription(): string {
        return parent::getDescription() . ", με γάλα";
    }
}

// Συγκεκριμένος Διακοσμητής: Προσθήκη ζάχαρης
class SugarDecorator extends CoffeeDecorator {
    public function getCost(): float {
        return parent::getCost() + 1.0;
    }

    public function getDescription(): string {
        return parent::getDescription() . ", με ζάχαρη";
    }
}

// Χρήση:
// Δημιουργία απλού καφέ
$coffee = new SimpleCoffee();
echo $coffee->getDescription() . " - " . $coffee->getCost() . "\n"; // Απλικός καφές - 5

// Προσθήκη γάλακτος
$coffeeWithMilk = new MilkDecorator($coffee);
echo $coffeeWithMilk->getDescription() . " - " . $coffeeWithMilk->getCost() . "\n"; // Απλικός καφές, με γάλα - 7

// Προσθήκη και ζάχαρης
$coffeeWithMilkAndSugar = new SugarDecorator($coffeeWithMilk);
echo $coffeeWithMilkAndSugar->getDescription() . " - " . $coffeeWithMilkAndSugar->getCost() . "\n"; // Απλικός καφές, με γάλα, με ζάχαρη - 8