Skip to content

nixel2007/decorator

Repository files navigation

decorator

Тестирование Статус порога качества

Библиотека для создания оберток (декораторов) над классами.

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

Возможности:

  • создание декоратора с идентичным интерфейсом;
  • синхронизация значений полей декоратора и реального объекта;
  • добавление методов, импортов, полей, шагов инициализации в runtime;
  • добавление перехватчиков ("перед", "после") вызова метода;
  • поддержка вложенных декораторов.

docs - todo;

Пример использования:

#Использовать decorator

КакойТоКласс = Новый КакойТоКласс();
КакойТоКласс.Поле = 123;

Поле = Новый Поле("НовоеПоле")
	.Публичное()
	.ЗначениеПоУмолчанию("ЗначениеПоУмолчанию");

Метод = Новый Метод("ДобавленнаяФункция")
	.Публичный()
	.ТелоМетода("Возврат Поле + 1;");

Перехватчик = Новый Перехватчик("ДобавленнаяФункция")
	.ТипПерехватчика(ТипыПерехватчиковМетода.Перед)
	.Тело("Сообщить(""Привет, мир!"")");

Декоратор = Новый ПостроительДекоратора(КакойТоКласс)
    .Импорт(Новый Импорт("fs"))
    .Поле(Поле)
    .Метод(Метод)
    .Перехватчик(Перехватчик)
    .Построить();

Ожидаем.Что(Декоратор.Поле).Равно(123);
Ожидаем.Что(Декоратор.РоднаяФункцияВозвращающаяИстина()).ЭтоИстина();
Ожидаем.Что(Декоратор.ДобавленнаяФункция()).Равно(124);

Отладка добавляемых методов

Для того, что бы работал отладчик и заходил в добавленные методы нужно: Либо установить любое значение переменной окружения с именем OSCRIPT_DECORATOR_DEBUG. Либо вызвать у построителя метод Отладка()

Декоратор = Новый ПостроительДекоратора(КакойТоКласс)
    .Импорт(Новый Импорт("fs"))
    .Поле(Поле)
    .Метод(Метод)
    .Перехватчик(Перехватчик)
    .Отладка()
    .Построить();

Документация по методам

ПостроительДекоратора

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   Объект - Произвольный - Инстанс объекта, над которым нужно создать декоратор
//          - Тип          - Тип объекта, инстанс которого нужно создать и задекорировать
//          - Неопределено - Декоратор создаётся с нуля
//
Процедура ПриСозданииОбъекта(Объект = Неопределено)

Поле

// Добавляет в декоратор новое поле
//
// Параметры:
//   Поле - Поле - Добавляемое поле
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция Поле(Поле) Экспорт

Метод

// Добавляет в декоратор новый метод.
//
// Параметры:
//   Метод - Метод - Добавляемый метод.
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция Метод(Метод) Экспорт

Перехватчик

// Добавляет в декоратор перехватчик
//
// Параметры:
//   Перехватчик - Перехватчик - Добавляемый перехватчик
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция Перехватчик(Перехватчик) Экспорт

Импорт

// Добавляет в декоратор импорт библиотеки (#Использовать).
//
// Параметры:
//   Импорт - Импорт - Импорт библиотеки
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция Импорт(Импорт) Экспорт

ШагИнициализации

// Добавляет в декоратор шаг инициализации в тело модуля.
//
// Параметры:
//   ШагИнициализации - ШагИнициализации - Выполняемый шаг инициализации
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция ШагИнициализации(ШагИнициализации) Экспорт

ЗначениеПараметраКонструктораПоТипу

// Добавляет значение параметра для инициализации объекта, в случае создания декоратора из типа
//
// Параметры:
//   ЗначениеПараметра - Произвольный - Значение параметра конструктора по типу
//
//  Возвращаемое значение:
//   ПостроительДекоратора - Ссылка на текущий инстанс ПостроительДекоратора
//
Функция ЗначениеПараметраКонструктораПоТипу(ЗначениеПараметра) Экспорт

ТекстСценария

// Получить сконструированный текст сценария будущего декоратора
//
//  Возвращаемое значение:
//   Строка - Текст сценария декоратора
//
Функция ТекстСценария() Экспорт

Построить

// Сконструировать готовый декоратор по настройкам конструктора Декоратор.
//
// Параметры:
//   ТекстСценария - Строка - Текст сценария декоратора. Если не задан, формируется автоматически.
//
//  Возвращаемое значение:
//   Произвольный - Декоратор над объектом, переданным в конструктор Декоратор
//
Функция Построить(ТекстСценария = Неопределено) Экспорт

ЗарегистрироватьВСистемеТипов

// Сконструировать готовый декоратор по настройкам конструктора Декоратор,
//  и зарегистрировать его как новый тип в системе типов
//
// Параметры:
//   ИмяТипа - Строка - Имя, под которым тип будет зарегистрирован в системе
//
Процедура ЗарегистрироватьВСистемеТипов(ИмяТипа) Экспорт

Аннотация

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ИмяАннотации - Строка - Имя добавляемой аннотации
//
Процедура ПриСозданииОбъекта(ИмяАннотации)

Параметр

// Добавляет параметр аннотации, допускается указание одного безымянного параметра
//
// Параметры:
//   Значение - Строка, Число, Булево, Дата - Значение параметра
//   Имя      - Строка - Необязательный, имя параметра 
//
//  Возвращаемое значение:
//   Аннотация - Ссылка на текущий инстанс Аннотация
//
Функция Параметр(Значение, Имя = "") Экспорт

Импорт

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ПодключаемаяБиблиотека - Строка - Имя или путь подключаемой библиотеки
//
Процедура ПриСозданииОбъекта(ПодключаемаяБиблиотека)

ТипПодключения

// Устанавливает тип подключения библиотеки
//
// Параметры:
//   УстанавливаемыйТипПодключения - ТипыПодключенияБибилотек - Устанавливаемый тип подключения библиотеки
//
//  Возвращаемое значение:
//   Импорт - Ссылка на текущий инстанс Импорт
//
Функция ТипПодключения(УстанавливаемыйТипПодключения) Экспорт

Метод

// Конструктор
//
// Параметры:
//   ИмяМетода - Строка - Имя создаваемого метода
//
Процедура ПриСозданииОбъекта(ИмяМетода)

Аннотация

// Добавляет аннотацию метода
//
// Параметры:
//   Аннотация - Аннотация - Добавляемая аннотация
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция Аннотация(Аннотация) Экспорт

ТелоМетода

// Устанавливает тело метода
//
// Параметры:
//   ТелоМетода - Строка - Устанавливаемое тело метода
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция ТелоМетода(ТелоМетода) Экспорт

Параметр

// Добавляет параметр метода
//
// Параметры:
//   Параметр - ПараметрМетода - Добавляемый параметр метода
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция Параметр(Параметр) Экспорт

Публичный

// Устанавливает экспорт метода
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция Публичный() Экспорт

ЭтоПроцедура

// Устанавливает признак того что этот метод Процедура
//
//  Возвращаемое значение:
//   Метод - Ссылка на текущий инстанс Метод
//
Функция ЭтоПроцедура() Экспорт

ПараметрМетода

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ИмяПараметра - Строка - Имя параметра метода
//
Процедура ПриСозданииОбъекта(ИмяПараметра)

ПоЗначению

// Устанавливает Знач параметра
//
//  Возвращаемое значение:
//   ПараметрМетода - Ссылка на текущий инстанс ПараметрМетода
//
Функция ПоЗначению() Экспорт

ЗначениеПоУмолчанию

// Устанавливает значение по умолчанию для параметра
//
// Параметры:
//   ЗначениеПоУмолчаниюПараметра - Строка, Число, Дата, Булево, Неопределено - Значение параметра по умолчанию
//
//  Возвращаемое значение:
//   ПараметрМетода - Ссылка на текущий инстанс ПараметрМетода
//
Функция ЗначениеПоУмолчанию(ЗначениеПоУмолчаниюПараметра) Экспорт

Аннотация

// Добавляет аннотацию параметра
//
// Параметры:
//   Аннотация - Аннотация - Добавляемая аннотация
//
//  Возвращаемое значение:
//   ПараметрМетода - Ссылка на текущий инстанс ПараметрМетода
//
Функция Аннотация(Аннотация) Экспорт

Перехватчик

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ИмяПерехватываемогоМетода - Строка - Имя метода для которого предназначен перехватчик
//
Процедура ПриСозданииОбъекта(ИмяПерехватываемогоМетода)

Тело

// Устанавливает тело перехватчика
//
// Параметры:
//   ТелоПерехватчика - Строка - Устанавливаемое тело перехватчика
//
//  Возвращаемое значение:
//   Перехватчик - Ссылка на текущий инстанс Перехватчик
//
Функция Тело(ТелоПерехватчика) Экспорт

ТипПерехватчика

// Устанавливает тип перехватчика
//
// Параметры:
//   ТипПерехватчика - ТипыПерехватчиковМетода - Устанавливаемое тип перехватчика
//
//  Возвращаемое значение:
//   Перехватчик - Ссылка на текущий инстанс Перехватчик
//
Функция ТипПерехватчика(ТипПерехватчика) Экспорт

Поле

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ИмяПоля - Строка - Имя поля
//
Процедура ПриСозданииОбъекта(ИмяПоля)

Публичное

// Устанавливает Экспорт поля
//
//  Возвращаемое значение:
//   Поле - Ссылка на текущий инстанс Поле
//
Функция Публичное() Экспорт

ЗначениеПоУмолчанию

// Устанавливает значение по умолчанию для поля
//
// Параметры:
//   УстанавливаемоеЗначениеПоУмолчанию - Произвольный - Значение поля по умолчанию
//
//  Возвращаемое значение:
//   Поле - Ссылка на текущий инстанс Поле
//
Функция ЗначениеПоУмолчанию(УстанавливаемоеЗначениеПоУмолчанию) Экспорт

Аннотация

// Добавляет аннотацию поля
//
// Параметры:
//   Аннотация - Аннотация - Добавляемая аннотация
//
//  Возвращаемое значение:
//   Поле - Ссылка на текущий инстанс Поле
//
Функция Аннотация(Аннотация) Экспорт

ШагИнициализации

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   ТелоШага - Строка - тело шага инициализации
//
Процедура ПриСозданииОбъекта(ТелоШага)

Перечисление ТипыПерехватчиковМетода

Перед

Перехватчик вызывается перед выполнением перехватываемого метода

После

Перехватчик вызывается после выполнения перехватываемого метода

ПослеВызоваИсключения

Перехватчик вызывается если перехватываемый метод упал в исключение, в момент перед пробросом исключения

ПередСинхронизациейПолей

Перехватчик вызывается в самом начале, перед синхронизацией полей декоратора и оригинального метода

Перечисление ТипыПодключенияБибилотек

ПоИмени

Библиотека подключается по имени:

#Использовать fs

ПоПути

Библиотека подключается по пути к библиотеке:

#Использовать "./libs/myLib"

ВНИМАНИЕ: Ниже приведён API устаревшей версий конструктора декоратора, он будет удалён в последующих релизах, воспользуйтесь новой версией


Устаревший API

Пример использования

#Использовать decorator

КакойТоКласс = Новый КакойТоКласс();
КакойТоКласс.Поле = 123;

ИмяМетода = "ДобавленнаяФункция";
ТекстМетода = "Возврат Поле + 1;";

Декоратор = Новый КонструкторДекоратора(КакойТоКласс)
    .ДобавитьИмпортПоИмени("fs")
    .ДобавитьПубличноеПоле("НовоеПоле", "ЗначениеПоУмолчанию")
    .ДобавитьМетод(ИмяМетода, ТекстМетода)
    .ДобавитьПередВызовомМетода("ДобавленнаяФункция", "Сообщить(""Привет, мир!"");")
    .Построить();

Ожидаем.Что(Декоратор.Поле).Равно(123);
Ожидаем.Что(Декоратор.РоднаяФункцияВозвращающаяИстина()).ЭтоИстина();
Ожидаем.Что(Декоратор.ДобавленнаяФункция()).Равно(124);

Документация по методам

КонструкторДекоратора

ПриСозданииОбъекта

// Конструктор
//
// Параметры:
//   Объект - Произвольный - Инстанс объекта, над которым нужно создать декоратор.
//
Процедура ПриСозданииОбъекта(Объект) 

ДобавитьПриватноеПоле

// Добавляет в декоратор новое приватное поле.
//
// Параметры:
//   ИмяПоля - Строка - Имя добавляемого поля
//   ЗначениеПоля - Произвольный - Значение, которым необходимо проинициализировать добавляемое поле.
//                                 Если не задано, поле не инициализируется и содержит Неопределено.
//
//  Возвращаемое значение:
//   КонструкторДекоратора - Ссылка на текущий инстанс КонструкторДекоратора
//
Функция ДобавитьПриватноеПоле(ИмяПоля, ЗначениеПоля = Неопределено) 

ДобавитьПубличноеПоле

// Добавляет в декоратор новое публичное (экспортное) поле.
//
// Параметры:
//   ИмяПоля - Строка - Имя добавляемого поля
//   ЗначениеПоля - Произвольный - Значение, которым необходимо проинициализировать добавляемое поле.
//                                 Если не задано, поле не инициализируется и содержит Неопределено.
//
//  Возвращаемое значение:
//   КонструкторДекоратора - Ссылка на текущий инстанс КонструкторДекоратора
//
Функция ДобавитьПубличноеПоле(ИмяПоля, ЗначениеПоля = Неопределено) 

ДобавитьМетод

// Добавляет в декоратор новый публичный (экспортный) метод.
//
// Параметры:
//   ИмяМетода - Строка - Имя добавляемого метода.
//   ТекстМетода - Строка - Текст добавляемого метода. Допустимо использование многострочной строки.
//
//  Возвращаемое значение:
//   КонструкторДекоратора - Ссылка на текущий инстанс КонструкторДекоратора
//
Функция ДобавитьМетод(ИмяМетода, ТекстМетода) 

ДобавитьПередВызовомМетода

// Добавляет в декоратор перехватчик, срабатывающий перед вызовом указанного метода.
//
// Параметры:
//   ИмяМетода - Строка - Имя перехватываемого метода.
//   ТекстПерехватчика - Текст - Текст добавляемого перехватчика. Допустимо использование многострочной строки.
//
//  Возвращаемое значение:
//   КонструкторДекоратора - Ссылка на текущий инстанс КонструкторДекоратора
//
Функция ДобавитьПередВызовомМетода(ИмяМетода, ТекстПерехватчика) 

ДобавитьПослеВызоваМетода

// Добавляет в декоратор перехватчик, срабатывающий после вызова указанного метода.
//
// Параметры:
//   ИмяМетода - Строка - Имя перехватываемого метода.
//   ТекстПерехватчика - Текст - Текст добавляемого перехватчика. Допустимо использование многострочной строки.
//
//  Возвращаемое значение:
//   КонструкторДекоратора - Ссылка на текущий инстанс КонструкторДекоратора
//
Функция ДобавитьПослеВызоваМетода(ИмяМетода, ТекстПерехватчика) 

ДобавитьИмпортПоИмени

// Добавляет в декоратор импорт библиотеки (#Использовать) по имени библиотеки.
//
// Параметры:
//   ИмяБиблиотеки - Строка - Имя библиотеки.
//
//  Возвращаемое значение:
//   КонструкторДекоратора - Ссылка на текущий инстанс КонструкторДекоратора
//
Функция ДобавитьИмпортПоИмени(ИмяБиблиотеки) 

ДобавитьИмпортПоПути

// Добавляет в декоратор импорт библиотеки (#Использовать) по пути к библиотеке.
//
// Параметры:
//   ПутьКБиблиотеке - Строка - Путь к библиотеке. Можно использовать как абсолютный, так и относительный путь.
//
//  Возвращаемое значение:
//   КонструкторДекоратора - Ссылка на текущий инстанс КонструкторДекоратора
//
Функция ДобавитьИмпортПоПути(ПутьКБиблиотеке) 

ДобавитьШагИнициализации

// Добавляет в декоратор шаг инициализации в тело модуля.
//
// Параметры:
//   ТекстШага - Строка - Выполняемый код.
//
//  Возвращаемое значение:
//   КонструкторДекоратора - Ссылка на текущий инстанс КонструкторДекоратора
//
Функция ДобавитьШагИнициализации(ТекстШага) 

ТекстСценария

// Получить сконструированный текст сценария будущего декоратора
//
//  Возвращаемое значение:
//   Строка - Текст сценария декоратора
//
Функция ТекстСценария() 

Построить

// Сконструировать готовый декоратор по настройкам конструктора декоратора.
//
// Параметры:
//   ТекстСценария - Строка - Текст сценария декоратора. Если не задан, формируется автоматически.
//
//  Возвращаемое значение:
//   Произвольный - Декоратор над объектом, переданным в конструктор декоратора
//
Функция Построить(ТекстСценария = Неопределено) 

Модуль ОбработкаДекоратора

ИсходныйТип

// Получает тип объекта, вокруг которого построен декоратор (рекурсивно).
//
// Параметры:
//   Декоратор - Произвольный - Объект, у которого нужно найти исходный тип объекта
//
//  Возвращаемое значение:
//   Тип - Исходный тип объекта
//
Функция ИсходныйТип(Декоратор) 

СинхронизироватьПоля

// Синхронизировать значения экспортных полей двух объектов.
//
// Параметры:
//   ИсходныйОбъект - Произвольный - Источник значений свойств
//   Потребитель - Произвольный - Получатель значений свойств
//
Процедура СинхронизироватьПоля(ИсходныйОбъект, Потребитель) 

Модуль Константы_Декоратор

// Имя поля, в котором хранится ссылка на исходный объект.
Перем Поле_ИнстансОбъекта Экспорт;

Отладка добавляемых методов

Для того, что бы работал отладчик и заходил в добавленные методы нужно: Либо установить любое значение переменной окружения с именем OSCRIPT_DECORATOR_DEBUG. Либо вызвать у конструктора метод Отладка()

Декоратор = Новый КонструкторДекоратора(МойКласс)
    .ДобавитьМетод(ИмяМетода, ТекстМетода)
    .Отладка()
    .Построить();

Результат = Декоратор.ДобавленнаяФункция();