Sobes.tech
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