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