Назад к вопросам
Middle
107
questionbank
Как работает декоратор в PHP?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech 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