Декораторы

Разбираемся что это и в чем отличия

Часть 1, теоретическая

С ростом популярности таких инструментов как TypeScript и Babeljs все больше разработчиков пробуют новые экспериментальные фишки черновых и не только стандартов языка ECMAScript, именуемого по традиции — Javascript.

К таким экспериментальным фича относятся и декораторы. Или аннотации… Так декораторы или аннотации? О, а что это вообще?

С выходом новой версии Angular2, интерес к декораторам/аннотациям возрастает, так как это часть стандартного воркфлоу и кодовой базы новой версии популярного фреймворка.

Давайте разбираться что же это, а начнем мы с определений и прочей нудятины, но мы же хотим разобраться, верно?…

ООП паттерн Декоратор

В объектно ориентированном программировании паттерн декоратор относится к структурным шаблонам проектирования.

Структурные шаблоны — шаблоны проектирования, в которых рассматривается вопрос о том, как из классов и объектов образуются более крупные структуры.

Классическое определение Декоратора

Декоратор (англ. Decorator) — структурный шаблон проектирования, предназначенный для динамического подключения дополнительного поведения к объекту. Шаблон Декоратор предоставляет гибкую альтернативу практике создания подклассов с целью расширения функциональности.

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

И так, вроде бы ничего сложного. У нас есть некоторый класс или объект, который мы можем задекорировать — добавить новый функционал или даже изменить существующий.

Классическая реализация такого шаблона в ООП стиле выглядит так

Процесс инициализации в данном примере не очень удобен. Мы могли бы вынести код в некоторую функцию декорирования, которая сама создавал новые задекорированные объекты. Как-то так:

Но выходит, что каждый раз для разных объектов нам придется создавать свою функцию декоратор. А что если мы создадим универсальную функцию и зафиксируем интерфейс декоратора? Он мог бы выглядеть как-то так:

Получилась универсальная функция декорирования любого объекта. По сути мы меняем содержимое созданного объекта не используя наследование. Паттерн Декоратор по своей функциональности похож на паттерн Обертка(Wrapper).

Примеры не претендуют на идеальность, особенно “универсальная” функция декорирования.