Описывается структурный шаблон проектирования Декоратор, приведены описание и пример реализации.
Шаблон проектирования Декоратор обычно применяют в случае, когда надо добавить новую функциональность в какой-то уже используемый компонент приложения. Обычно для расширения функций объекта практикуется создание наследников, но, как видите, есть и альтернатива. Подобный путь обычно себя оправдывает в случае, если к компоненту надо добавлять достаточно много небольших функций, что при наследовании приведет к разрастанию системы классов. Шаблон также удобен, когда требуются однотипные компоненты с небольшими различиями в поведении.
При реализации Декоратора, как и в случае с шаблоном Адаптер, вокруг изменяемого компонента создается обертка, с помощью которой и добавляются новые методы. Их можно добавлять как до выполнения кода изменяемого объекта, так и после. Разница между шаблонами в том, что интерфейс Адаптера отличается от изменяемого объекта, а интерфейс Декоратора совпадает с интерфейсом изменяемого объекта. Ну, вроде можно приступать к примеру реализации.
Удобно реализовать шаблон через абстрактные классы, это позволит в дальнейшем легко модифицировать приложение на базе абстракций. Смысл предыдущего утверждения будет понятен после пояснений кода. Итак, приступим.
//родитель компонента приложения, определяющий набор его базовых функций
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.
Перейти к списку шаблонов проектирования.