Декораторы в TypeScript

В TypeScript, начиная с версии 1.5, появилась поддержка шаблона "декоратор". Давайте разберемся как и зачем его можно использовать.

В первую очередь вспомним для чего необходим указанный шаблон:

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

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

Из статьи "Структурные шаблоны: Декоратор (Decorator)"

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

Декоратор в TypeScript это обычная функция, объявленная следующим образом:

function decoratorName(target: Function, key: string, value: any) {
    return {
        value: (...args: any[]) => {
            // Код выполняемый до вызова декорируемого метода           

            // Вызов исходного метода
            var result = value.value.apply(this, args);

            // Код выполняемый после вызова декорируемого метода

            return result;
        }
    };
}

В качестве параметров передаются:

  • target – прототип класса, в котором установлен данный декоратор;
  • key – имя метода (функции, свойства) на котором установлен декоратор;
  • value – дескриптор метода (функции, свойства), на который установлен декоратор. Сам метод можно получить обратившись к value.vaule.

Функция декоратора должна вернуть новый дескриптор. В его свойстве value располагается код, который будет вызываться при обращениях к декорируемому методу, параметры которого так же будут переданы в виде массива args.

Чтобы установить декоратор используется следующий синтаксис:

class SomeClass {
    @decoratorName
    SomeMethod(…) { … }
}

В качестве примера, создадим декоратор, который выводит на консоль браузера сообщения о вызовах декорируемого метода со списком его параметров и значением результата:

function logCall(target: Function, key: string, value: any) {
    return {
        value: (...args: any[]) => {

            // создаем строку значениями параметров
            var a = args.map(a => JSON.stringify(a)).join();

            // вызываем декорируемый метод
            var result = value.value.apply(this, args);

            // создаем строку с результатом работы метода
            var r = JSON.stringify(result);

            // выводим на консоль строку с вызовом функции
            console.log("Вызов: ${key}(${a}) > ${r}");

            // возвращаем результат
            return result;
        }
    };
}

class DecoratorDemo {
    @logCall
    Add(n1: number, n2: number): number {
        return n1 + n2;
    }
}

Комментарии (4) -

Алексей 19.04.2015 22:59:02

Хочу: Web - фреймворк с паттерном mvvm что бы все можно было делать на C#
(без js и tj). Где взять?

Алексей - видимо нигде, т.к. браузеры не умеют исполнять C# код. Использовать C# > JS конверторы тоже не очень хорошая идея.

Алексей 25.04.2015 2:22:04

А вот что ни будет вроде такого нельзя сделать: http://habrahabr.ru/company/xakep/blog/244477/ К стати, на чем у Вас сайт написан, если не секрет(фремворк какой)?

Алексей Трансляцию C# > JavaScript? Можно и даже есть такие проекты. Вот только в реальном проекте я бы не стал такое использовать (именно если речь о C#/Java трансляторах). Я думаю проблем будет больше чем плюсов от использования, т.к. далеко не все можно однозначно транслировать. А еще есть библиотеки. Для сравнения - TypeScript (и например CoffeeScript) изначально задумывались для этой цели.

Насчет движка блога - все есть в футере.

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