Middle
Ako funguje dekorátor v PHP?
sobes.tech AI
Odpoveď od AI
Vzor "Dekorátor" dynamicky pridáva nové správanie existujúcemu objektu tým, že ho obalí do iného objektu nazývaného dekorátor.
-
Zložky:
- Rozhranie (Component): Deklaruje spoločné metódy pre pôvodný objekt a jeho dekorátory.
- Konkrétny komponent (Concrete Component): Hlavný objekt, ktorý je potrebné dekorovať.
- Základný dekorátor (Decorator): Abstraktná trieda alebo rozhranie, ktoré obsahuje odkaz na objekt rozhrania (Component) a implementuje jeho metódy, zvyčajne delegovaním volania na tento objekt.
- Konkrétne dekorátory (Concrete Decorators): Implementujú nové možnosti, dopĺňajú alebo menia správanie základného komponentu.
-
Princíp fungovania:
- Dekorátor obsahuje odkaz na objekt, ktorý dekoruje (kompozícia).
- Dekorátor má rovnaké rozhranie, ako dekorovaný objekt.
- Pri volaní metódy u dekorátora, buď vykonáva dodatočnú logiku pred alebo po volaní zodpovedajúcej metódy u dekorovaného objektu, alebo ho úplne nahradí (hoci posledné nie je typické použitie).
-
Výhody:
- Umožňuje pridávať funkcionalitu k objektom za behu, nie cez statické dedičstvo.
- Vyhýba sa "výbuchu" hierarchie tried pri kombinovaní rôznych správaní.
- Umožňuje vytvárať flexibilné kombinácie správaní.
-
Príklad:
<?php
// Rozhranie komponenty
interface Coffee {
public function getCost(): float;
public function getDescription(): string;
}
// Konkrétny komponent
class SimpleCoffee implements Coffee {
public function getCost(): float {
return 5.0;
}
public function getDescription(): string {
return "Jednoduchá káva";
}
}
// Abstraktný dekorátor
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();
}
}
// Konkrétny dekorátor: pridanie mlieka
class MilkDecorator extends CoffeeDecorator {
public function getCost(): float {
return parent::getCost() + 2.0;
}
public function getDescription(): string {
return parent::getDescription() . ", s mliekom";
}
}
// Konkrétny dekorátor: pridanie cukru
class SugarDecorator extends CoffeeDecorator {
public function getCost(): float {
return parent::getCost() + 1.0;
}
public function getDescription(): string {
return parent::getDescription() . ", so cukrom";
}
}
// Použitie:
// Vytvorenie jednoduchého coffee
$coffee = new SimpleCoffee();
echo $coffee->getDescription() . " - " . $coffee->getCost() . "\n"; // Jednoduchá káva - 5
// Pridanie mlieka
$coffeeWithMilk = new MilkDecorator($coffee);
echo $coffeeWithMilk->getDescription() . " - " . $coffeeWithMilk->getCost() . "\n"; // Jednoduchá káva, s mliekom - 7
// Pridanie cukru
$coffeeWithMilkAndSugar = new SugarDecorator($coffeeWithMilk);
echo $coffeeWithMilkAndSugar->getDescription() . " - " . $coffeeWithMilkAndSugar->getCost() . "\n"; // Jednoduchá káva, s mliekom, so cukrom - 8