Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Реализация паттерна Декоратор в PHP
Паттерн Декоратор (Decorator) — это структурный паттерн проектирования, который позволяет динамически добавлять объектам новую функциональность, оборачивая их в полезные «обёртки». Это гибкая альтернатива наследованию для расширения функциональности.
Базовые концепции
Основная идея декоратора заключается в создании цепочки объектов, где каждый последующий декоратор добавляет свою функциональность к предыдущему. Все декораторы реализуют тот же интерфейс, что и исходный объект, что позволяет им быть взаимозаменяемыми.
Ключевые компоненты
- Интерфейс Компонента — определяет общий интерфейс для всех компонентов
- Конкретный Компонент — исходный объект, который нужно декорировать
- Базовый Декоратор — абстрактный класс, реализующий тот же интерфейс
- Конкретные Декораторы — добавляют конкретную функциональность
Пример реализации
<?php
// 1. Интерфейс Компонента
interface NotifierInterface
{
public function send(string $message): string;
}
// 2. Конкретный Компонент
class EmailNotifier implements NotifierInterface
{
public function send(string $message): string
{
return "Отправка email: $message";
}
}
// 3. Базовый Декоратор
abstract class NotifierDecorator implements NotifierInterface
{
protected NotifierInterface $notifier;
public function __construct(NotifierInterface $notifier)
{
$this->notifier = $notifier;
}
public function send(string $message): string
{
return $this->notifier->send($message);
}
}
// 4. Конкретные Декораторы
class SMSDecorator extends NotifierDecorator
{
public function send(string $message): string
{
$baseResult = parent::send($message);
return $baseResult . "\nОтправка SMS: $message";
}
}
class SlackDecorator extends NotifierDecorator
{
public function send(string $message): string
{
$baseResult = parent::send($message);
return $baseResult . "\nОтправка в Slack: $message";
}
}
class LoggingDecorator extends NotifierDecorator
{
public function send(string $message): string
{
$result = parent::send($message);
$logMessage = "Логирование: " . date('Y-m-d H:i:s') . " - $message";
return $result . "\n$logMessage";
}
}
// Использование
$notifier = new EmailNotifier();
// Добавляем функциональность динамически
$notifier = new SMSDecorator($notifier);
$notifier = new SlackDecorator($notifier);
$notifier = new LoggingDecorator($notifier);
echo $notifier->send("Важное уведомление!");
Преимущества паттерна Декоратор
- Гибкость: Можно динамически добавлять и комбинировать функциональность
- Соблюдение принципа открытости/закрытости: Классы открыты для расширения, но закрыты для изменений
- Избегание взрывного роста классов: Не нужно создавать множественные подклассы для каждой комбинации функциональности
- Принцип единой ответственности: Каждый декоратор отвечает за одну конкретную задачу
Отличия от других паттернов
В отличие от Наследования:
- Декоратор позволяет изменять поведение объектов во время выполнения
- Не создаёт жесткой иерархии классов
- Более гибкая композиция функциональности
В отличие от Цепочки обязанностей:
- В декораторе каждый элемент обрабатывает запрос и передаёт его дальше
- В цепочке обязанностей обработчик может прервать цепочку
Практические примеры использования в PHP
- Обработка HTTP-запросов и ответов:
interface ResponseInterface {
public function send(): string;
}
class JsonResponseDecorator implements ResponseInterface {
private ResponseInterface $response;
public function send(): string {
$data = $this->response->send();
return json_encode(['data' => $data, 'timestamp' => time()]);
}
}
- Кэширование:
class CacheDecorator implements DataProviderInterface {
private DataProviderInterface $provider;
private CacheInterface $cache;
public function getData(string $key): array {
if ($this->cache->has($key)) {
return $this->cache->get($key);
}
$data = $this->provider->getData($key);
$this->cache->set($key, $data);
return $data;
}
}
- Валидация и фильтрация:
class SanitizeDecorator implements InputInterface {
private InputInterface $input;
public function getValue(): string {
$value = $this->input->getValue();
return htmlspecialchars(strip_tags(trim($value)));
}
}
Рекомендации по использованию
- Используйте декоратор, когда нужно добавлять обязанности объектам динамически и прозрачно
- Избегайте создания слишком длинных цепочек декораторов
- Убедитесь, что декораторы действительно независимы друг от друга
- Помните о принципе подстановки Барбары Лисков — декоратор должен быть полностью взаимозаменяем с исходным компонентом
Паттерн Декоратор особенно полезен в PHP-приложениях для реализации middleware, обработчиков событий, систем кэширования и логгирования, где требуется гибкая композиция поведения без изменения исходного кода.