Описывается структурный шаблон проектирования Decorator, приведены описание и пример реализации.
Содержание
- Область применения
- Реализация
- Итоги
Область применения
Шаблон проектирования Decorator обычно применяют в случае, когда надо добавить новую функциональность в какой-то уже используемый компонент приложения. Обычно для расширения функций объекта практикуется создание наследников, но, как видите, есть и альтернатива. Применение шаблона удобно, например, в таких случаях:
- если к компоненту надо добавлять достаточно много небольших функций, что при наследовании приведет к разрастанию системы похожих классов;
- шаблон удобен, если требуются однотипные компоненты с небольшими различиями в поведении.
Реализация
При реализации Декоратора, как и в случае с шаблоном Адаптер, вокруг изменяемого компонента создается обертка, с помощью которой и добавляются новые методы. Их можно добавлять как до выполнения кода изменяемого объекта, так и после. В отличие от шаблона Адаптер интерфейс Декоратора совпадает с интерфейсом изменяемого объекта. Ну, вроде можно приступать к примеру реализации.
Удобно реализовать шаблон через абстрактные классы, это позволит в дальнейшем легко модифицировать приложение на базе абстракций. Смысл предыдущего утверждения будет понятен после пояснений кода. Итак, приступим.
//родитель компонента приложения, определяющий набор его базовых функций
abstract class AbstractComponent
{
abstract public function operation();
...
}
//здесь реализуется набор базовых функций компонента приложения
class Component1 extends AbstractComponent
{
//определяем задекларированный в абстрактном классе метод
public function operation()
{
// ... реализация
}
// ... реализация других базовых функций компонента
}
//абстрактный класс, определяющий основной набор новых функций
abstract class AbstractDecorator extends AbstractComponent
{
protected $component;
public function __construct(AbstractComponent $component)
{
$this->component = $component;
}
// ... реализация других основных новых функций компонента при необходимости
}
// набор1 новых функций компонента
class ComponentDecorator1 extends AbstractDecorator
{
public function operation()
{
// ... расширенная функциональность, выполняемая до основных
$this->component->operation();
// ... расширенная функциональность, выполняемая после основных
}
}
// набор2 новых функций компонента
class ComponentDecorator2 extends AbstractDecorator
{
public function operation()
{
// ... расширенная функциональность, выполняемая до основных
$this->component->operation();
// ... расширенная функциональность, выполняемая после основных
}
}
Итоги
Надеюсь, все достаточно понятно из комментариев. Хочется только резюмировать следующее.
В классе AbstractComponent задаем функциональность нашего компонента.
В классе AbstractDecorator задается одна и больше новых функций изменяемого компонента. Кроме того, при создании экземпляра декоратора ему передается ссылка на исходный компонент, это позволяет его использование без изменений.
В классе ComponentDecorator1 реализуется новое поведение изменяемого компонента.
В случае необходимости дальнейшей модификации функционала компонента мы легко это реализуем с помощью другого декоратора, создав, в частности, новый класс ComponentDecorator2.
Перейти к списку шаблонов проектирования.