Sobes.tech
Middle

Cum funcționează un decorator în PHP?

sobes.tech AI

Răspuns de la AI

Modelul "Decorator" adaugă dinamic un comportament nou unui obiect existent învelindu-l într-un alt obiect numit decorator.

  • Componente:

    • Interfață (Component): Declară metode comune pentru obiectul original și decoratorii săi.
    • Component concret (Concrete Component): Obiectul principal care trebuie decorat.
    • Decorator de bază (Decorator): Clasă abstractă sau interfață care conține o referință la un obiect al interfeței (Component) și implementează metodele sale, de obicei delegând apelul către acel obiect.
    • Decoratori concreți (Concrete Decorators): Implementează noi funcționalități, completând sau modificând comportamentul componentului de bază.
  • Principiul de funcționare:

    • Decoratorul conține o referință la obiectul pe care îl decorează (compoziție).
    • Are aceeași interfață ca obiectul decorat.
    • La apelarea unei metode pe decorator, acesta efectuează logică suplimentară înainte sau după apelul metodei corespunzătoare pe obiectul decorat, sau îl înlocuiește complet (deși acesta din urmă nu este o utilizare tipică).
  • Avantaje:

    • Permite adăugarea de funcționalități obiectelor în timpul execuției, nu static prin moștenire.
    • Evită "explozia" ierarhiei de clase la combinarea mai multor comportamente diferite.
    • Permite crearea de combinații flexibile de comportamente.
  • Exemplu:

<?php

// Interfața componentului
interface Coffee {
    public function getCost(): float;
    public function getDescription(): string;
}

// Component concret
class SimpleCoffee implements Coffee {
    public function getCost(): float {
        return 5.0;
    }

    public function getDescription(): string {
        return "Cafea simplă";
    }
}

// Decorator de bază
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();
    }
}

// Decorator concret: Adăugare lapte
class MilkDecorator extends CoffeeDecorator {
    public function getCost(): float {
        return parent::getCost() + 2.0;
    }

    public function getDescription(): string {
        return parent::getDescription() . ", cu lapte";
    }
}

// Decorator concret: Adăugare zahăr
class SugarDecorator extends CoffeeDecorator {
    public function getCost(): float {
        return parent::getCost() + 1.0;
    }

    public function getDescription(): string {
        return parent::getDescription() . ", cu zahăr";
    }
}

// Utilizare:
// Creăm o cafea simplă
$coffee = new SimpleCoffee();
echo $coffee->getDescription() . " - " . $coffee->getCost() . "\n"; // Cafea simplă - 5

// Adăugăm lapte
$coffeeWithMilk = new MilkDecorator($coffee);
echo $coffeeWithMilk->getDescription() . " - " . $coffeeWithMilk->getCost() . "\n"; // Cafea simplă, cu lapte - 7

// Adăugăm zahăr
$coffeeWithMilkAndSugar = new SugarDecorator($coffeeWithMilk);
echo $coffeeWithMilkAndSugar->getDescription() . " - " . $coffeeWithMilkAndSugar->getCost() . "\n"; // Cafea simplă, cu lapte, cu zahăr - 8