Структурный шаблон программирования Декоратор

«Декоратор» (Decorator) является одним из классических структурных шаблонов проектирования, позволяющим динамически добавлять новые обязанности объектам без изменения их базовой структуры. По сути, декораторы расширяют возможности существующих объектов путем обертывания их новыми слоями поведения, сохраняя при этом оригинальную реализацию класса.


Ключевые особенности и цели

Цель декоратора — обеспечивать расширение возможностей объектов посредством композиции, то есть комбинируя небольшие компоненты в большие конструкции без изменения базовых классов. Основное преимущество — гибкость, так как декораторы позволяют применять дополнительные функции к объекту прямо во время исполнения программы, избегая наследования.

Обычно применяют этот шаблон, когда требуется расширить поведение объекта постепенно, без внесения кардинальных изменений в существующую структуру классов.


Компоненты модели

При использовании паттерна «Декоратор» выделяют следующие основные элементы:

  • Компонент (Component): базовый абстрактный класс или интерфейс, определяющий поведение объекта, которое будет декорировано.
  • Конкретный компонент (Concrete Component): реализация базового компонента, содержащего основную бизнес-логику.
  • Абстрактный декоратор (Decorator): определяет интерфейс и хранит ссылку на объект-компонент, над которым осуществляется декорирование.
  • Конкретный декоратор (Concrete Decorator): добавляет новую функциональность к базовому компоненту.

Пример реализации на PHP

Давайте рассмотрим практический пример, демонстрирующий концепцию декоратора. Допустим, у нас есть веб-сервис отправки сообщений, и нам необходимо реализовать две дополнительные опции: шифрование и подпись сообщений.

Базовый компонент (MessageSenderInterface)

interface MessageSenderInterface {
    public function send(string $message): void;
}

Конкретный компонент (SimpleMessageSender)

class SimpleMessageSender implements MessageSenderInterface {
    public function send(string $message): void {
        echo "Сообщение отправлено: {$message}\n";
    }
}

Абстрактный декоратор (MessageDecorator)

abstract class MessageDecorator implements MessageSenderInterface {
    protected $wrapped;

    public function __construct(MessageSenderInterface $component) {
        $this->wrapped = $component;
    }

    public function send(string $message): void {
        $this->wrapped->send($message);
    }
}

Конкретный декоратор (EncryptionDecorator)

class EncryptionDecorator extends MessageDecorator {
    public function send(string $message): void {
        $encryptedMessage = strrev($message); // примитивное шифрование обратным порядком букв
        parent::send($encryptedMessage);
    }
}

Еще один конкретный декоратор (SignatureDecorator)

class SignatureDecorator extends MessageDecorator {
    public function send(string $message): void {
        $signedMessage = $message . " (подписано)";
        parent::send($signedMessage);
    }
}

Использование декоратора

Теперь посмотрим, как всё это собирается вместе:

$simpleSender = new SimpleMessageSender();

// Применяем сначала подпись, потом шифрование
$decoratedSender = new EncryptionDecorator(new SignatureDecorator($simpleSender));

$decoratedSender->send("Привет мир!");

В результате выполнения приведенного примера вывод будет следующим:

Сообщение отправлено: !рим тевирП (подписано)

Видите, как порядок наложения слоев влияет на итоговое поведение?


Преимущества и недостатки

Преимущества:

  • Гибкое расширение функционала объектов.
  • Легко интегрируется с существующими структурами без переписывания основной логики.
  • Позволяет избежать множественного наследования, оставаясь открытым для дальнейшего расширения.

Недостатки:

  • Возможно чрезмерное усложнение, если используются многочисленные слои декораций.
  • Сложность отслеживания последовательности применения декораторов.

Заключение

Шаблон «Декоратор» прекрасно решает задачу постепенного расширения функциональных возможностей объектов без изменения их базовой структуры. Особенно удобно его использовать, когда нужны разнообразные комбинации модификаций, поскольку позволяет гибко настраивать нужное поведение.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *