Принципы ООП в 1С на примере реализации pattern Decorator

Публикация № 850699

Разработка - Математика и алгоритмы

ООП pattern Decorator Decorator GoF pattern ООП в 1С

В данной статье будет рассмотрен пример реализации GoF паттерна проектирования decorator в среде разработки 1С. Основная цель данного шаблона, это возможность динамического расширения функциональности базового класса. Сразу оговорюсь, т.к. в 1С нет ООП, это будет не чистый пример реализации данного шаблона, однако свою задачу данный пример будет решать.

 

Для начала ознакомимся с UML диаграммой шаблона decorator

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

Давайте "на берегу" определимся с понятиями интерфейс и класс в 1С. Таких понятий в 1С нет, однако если провести параллели, то наиболее близкая к классу сущность, это обработка. С интерфейсом сложнее, можно конечно реализовать паттерн и без интерфейса, но тогда не будет той необходимой и полезной абстракции. В статье Строим "фасады" в 1С автор использовал для аналогии интерфейса общие модули, общий модуль не очень подходит для данной задачи, по факту это будет просто обертка вокруг класса. В данном примере в качестве интерфейса я буду использовать так же обработку. 

 

Приступим к реализации. 

Например, перед нами стоит задача реализовать алгоритм поиска контрагента.

создаем обработку с экспортным методом в модуле объекта НайтиКонтрагента(ИНН, КПП); вызов из кода будет такой

Объект = Обработки.ПоискКонтрагента.Создать();
Контрагент = Объект.НайтиКонтрагента(ИНН, КПП); // Какой-то ИНН и какой-то КПП

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

 

Давайте подумаем, какую роль выполняет интерфейс в ООП? Как нам подсказывает вики 

устанавливают взаимные обязательства между элементами программной системы

Если своими словами, то объявленные методы в интерфейсе обязательно должны быть реализованы в каждом классе который реализует этот интерфейс.

Для реализации интерфейса создаем новую обработку "ПоискКонтрагентаИнтерфейс". Содержащая реквизит РеализующийОбъект, тип ОбработкаОбъект.ПоискКонтрагента (или составной, для случаев если данный интерфейс имплементируют несколько классов)

Содержимое модуля объекта

 

Метод Имплементация - основной, он делает проверку на существования в реализующем классе необходимых методов (правда коряво эта проверка происходит), так же инициализирует значением реквизит РеализующийОбъект.

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


В обработку ПоискКонтрагента добавляем реквизит БазовыйОбъект, тип составной (типы от которых может наследоваться этот класс) модуль объекта обработки добавляем методы Имплементация().

Функция Имплементация(ИнтерфейсИмя) Экспорт 
	Возврат Обработки[ИнтерфейсИмя].Создать().Имплементация(ЭтотОбъект);
КонецФункции

и Наследовать() 

Функция Наследовать(БазовыйОбъект) Экспорт 
	ЭтотОбъект.БазовыйОбъект = БазовыйОбъект;	
	Возврат ЭтотОбъект;
КонецФункции

 На текущем этапе БазовыйОбъект нам по большому счету не нужен, но давайте придерживаться одного шаблона, не важно наш класс наследуется от другого или нет, структура должна быть шаблонная.

В начале метода НайтиКонтрагента делаем проверку

Если ДанныеВерсии.Свойство("РежимПроверки") И ДанныеВерсии.РежимПроверки Тогда
  Возврат Неопределено;	
КонецЕсли;

Это нужно для метода ПроверитьСуществованиеМетодов (который у нас в модуле Интерфейсы). Ну нет у 1С нормального способа проверить существует ли метод в модуле объекта или нет.


Вот так изменится вызов метода НайтиКонтрагента

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


 

Зачем такие сложности скажите вы, зато теперь мой "интерфейс" могут имплементировать разные обработки разной структуры и разными методами, но мы 100% уверены, что у любой обработки есть нужный нам метод и мы можем вызвать его используя интерфейс.

На данном этапе мы реализовали эту часть диаграммы: 


Теперь реализуем сам декоратор.

Пусть наш декоратор расширяет алгоритм таким образом, что бы в случаи если не найден контрагент, он создавался.

Для этого создаем еще один класс обработку Декоратор1, копия обработки ПоискКонтрагента 

Единственное изменение, это доработанный метод НайтиКонтрагента(), доработан он таким образом:

Функция НайтиКонтрагента(Данные) Экспорт 
	Если ДанныеВерсии.Свойство("РежимПроверки") И ДанныеВерсии.РежимПроверки Тогда
		Возврат Неопределено;	
	КонецЕсли;

	Версия = БазовыйОбъект.НайтиКонтрагента(Данные); // Вызываем поиск базового объекта.
// Дополнение которое привносит декоратор.
	Если Не ЗначениеЗаполнено(Версия) Тогда
		Версия = СоздатьКонтрагента(ДанныеВерсии);	
	КонецЕсли;
	
	Возврат Версия;
КонецФункции
Функция СоздатьКонтрагента(ДанныеВерсии)
	// Создаем.	
	Сообщить("Создаем новый элемент справочника"); // Для демонстрации, что вызов есть.
КонецФункции

Тип реквизита БазовыйОбъект составной, по сути все типы от которых может наследоваться этот класс, а именно ПоискКонтрагента, ПоискКонтрагентаИнтерфейс. Данный класс так же реализует интерфейс ПоискСправочникаИнтерфейс, по этому у его реквизита РеализующийОбъект нужно сделать так же составной тип в который входит новый класс. Кстати это удобней делать через определяемые типы. 

Вызов будет таким:

Данные = Новый Структура("ИНН, КПП", КакойтоИНН, КакойтоКПП); // Входящий параметр теперь один, структура.
Интерфейс = Обработки.ПоискСправочника.Создать().Имплементация("ПоискСправочникаИнтерфейс");
Декоратор1 = Обработки.Декоратор1.Создать()
								.Наследовать(Интерфейс)
								.Имплементация("ПоискСправочникаИнтерфейс");
Контрагент = Декоратор1.НайтиКонтрагента(Данные);

Обращаю внимание, что декоратор наследуется от интерфейса и новый объект так же имплементирует ПоискКонтрагентаИнтерфейс

Если мы захотим еще обернуть, то просто создаем копию декоратора 1 и реализуем в нем свои изменения, в моем примере это вывод еще одного сообщения (не забываем про типы реквизитов БазовыйОбъект и РеализующийОбъект)

Функция СоздатьКонтрагента(ДанныеВерсии)
	Сообщить("Что-то делаем"); // Для демонстрации, что вызов есть.
КонецФункции

Вызов изменится так: 

Данные = Новый Структура("ИНН, КПП", КакойтоИНН, КакойтоКПП); // Входящий параметр теперь один, структура.
Интерфейс = Обработки.ПоискСправочника.Создать().Имплементация("ПоискСправочникаИнтерфейс");
Декоратор1 = Обработки.Декоратор1.Создать()
								.Наследовать(Интерфейс)
								.Имплементация("ПоискСправочникаИнтерфейс");

Декоратор2 = Обработки.Декоратор2.Создать()
								.Наследовать(Декоратор1)
								.Имплементация("ПоискСправочникаИнтерфейс");
Контрагент  = Декоратор2.НайтиКонтрагента(Данные);

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

 

Вот результат 

хотя как мы видим вызов метода происходит один раз.


В итоге у нас вышла такая реализация

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

Спасибо за внимание!

 

Скачать файлы

Наименование Файл Версия Размер
Принципы ООП в 1С на примере реализации pattern Decorator:

.zip 12,71Kb
27.06.18
4
.zip 12,71Kb 4 Скачать

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. PerlAmutor 122 21.06.18 18:52 Сейчас в теме
Функция НайтиКонтрагента(Данные) Экспорт 
	Если ДанныеВерсии.Свойство("РежимПроверки") И ДанныеВерсии.РежимПроверки Тогда
		Возврат Неопределено;	
	КонецЕсли;


(0) Это можно немного улучшить, на мой взгляд, таким образом:

		Попытка
			 Выполнить(СтрШаблон("Объект.%1(, Истина)", Метод));
		Исключение
			 ОтсутствующиеМетоды.Добавить(Метод);
		КонецПопытки;
...
Функция НайтиКонтрагента(Данные = Неопределено, РежимПроверки = Ложь) Экспорт 
	Если РежимПроверки Тогда
		Возврат Неопределено;	
	КонецЕсли;
Показать
2. lazarenko 217 21.06.18 19:11 Сейчас в теме
(1) можно, только это ничего ж не меняет. Просто в моем варианте хорошо то, что параметр у метода один
3. PerlAmutor 122 21.06.18 19:22 Сейчас в теме
(2) Тоже верно. Тогда вопрос, тут ошибки нет случаем? А то параметр называется "Данные", а поиск свойства идет у "ДанныеВерсии":

Функция НайтиКонтрагента(Данные) Экспорт 
	Если ДанныеВерсии.Свойство("РежимПроверки") И ДанныеВерсии.РежимПроверки Тогда
		Возврат Неопределено;	
	КонецЕсли;
4. lazarenko 217 22.06.18 08:08 Сейчас в теме
(3) да это я ошибся когда в статью переносил, в приаттаченных обработках нор.
5. l1ike 16.07.18 07:52 Сейчас в теме
Ну раз уж интерфейсы в 1с появились, давайте уже и статические типы прикручивайте )))
Вы соответствие объекта интерфейсу когда проверять планируете? При старте программы или при создании объекта? Если при создании объекта, то выгода от интерфейсов, по моему, весьма сомнительна. А если при старте программы, тогда проще как в javascript транспиляторы писать.
6. s_vidyakin 11.01.19 18:08 Сейчас в теме
Данные = Новый Структура("ИНН, КПП", КакойтоИНН, КакойтоКПП); // Входящий параметр теперь один, структура.
Интерфейс = Обработки.ПоискСправочника.Создать().Имплементация("ПоискСправочникаИнтерфейс");
Декоратор1 = Обработки.Декоратор1.Создать().Наследовать(Интерфейс).Имплементация("ПоискСправочникаИнтерфейс");
Контрагент = Декоратор1.НайтиКонтрагента(Данные);

Не превращайте 1С в богомерзкую яву! ))
Оставьте свое сообщение

См. также

Многопоточность. Универсальный «Менеджер потоков» (фреймворк) с отслеживанием зависимости объектов Промо

Практика программирования Математика и алгоритмы Универсальные функции Производительность и оптимизация (HighLoad) v8 1cv8.cf Россия Абонемент ($m)

Восстановление партий, расчет зарплаты, пакетное формирование документов или отчетов - теперь все это стало доступнее. * Есть желание повысить скорость работы медленных алгоритмов! Но... * Нет времени думать о реализации многопоточности? * о запуске и остановке потоков? * о поддержании потоков в рабочем состоянии? * о передаче данных в потоки и как получить ответ из потока? * об организации последовательности? Тогда ЭТО - то что надо!!!

26.05.2017    49330    DarkAn    86    

Еще раз о рабочих днях. Быстрый способ расчета в запросах

Практика программирования Математика и алгоритмы Разработка v8 Абонемент ($m)

В статье рассмотрен механизм учета производственных графиков и рабочих дней. Предложен простой и быстрый алгоритм решения типичных задач: добавление рабочих дней к дате и нахождение разницы между датами в рабочих днях. Все вычисления производятся исключительно запросом, т.е. решение пригодно для СКД и динамических списков.

1 стартмани

20.06.2019    7912    Alxby    11    

Функциональное программирование в 1С

Практика программирования Математика и алгоритмы Разработка v8 1cv8.cf Абонемент ($m)

Статья о функциональном программировании в 1С. Добавляем новые возможности. Пример передачи функций в качестве аргумента.

1 стартмани

28.03.2019    8470    alexey.kutya    26    

Агрегатное суммирование строк в запросе – сложно, но не невозможно Промо

Математика и алгоритмы v8 Абонемент ($m)

Описывается метод соединения строк из одной колонки таблицы в единую результирующую строку в запросе на языке 1С. Метод сложный и по сравнению с внезапросной техникой представляет больше спортивный, чем практический интерес.

1 стартмани

09.09.2013    79174    ildarovich    54    

Иерархия библиотек. Автоматическое обновление или как отказаться от переопределяемых модулей

Практика программирования Математика и алгоритмы Разработка v8 Абонемент ($m)

В статье рассмотрен один из вариантов библиотечного подхода к разработке, позволяющий организовать иерархический вызов библиотечных процедур и упростить автоматическую сборку готового продукта из нескольких библиотек. Предлагаемый подход может служить одним из элементов CI/CD при разработке ПО на платформе 1С.

1 стартмани

04.03.2019    5817    Alxby    4    

Принципы ООП в 1С (pattern observer)

Практика программирования v8 Абонемент ($m)

Продолжаем рассматривать принципы ООП в 1С, сегодня речь пойдет про такой шаблон проектирования, как observer.

1 стартмани

04.07.2018    6694    lazarenko    17    

Жизненный цикл управляемой формы. Шпаргалка разработчика

Практика программирования Математика и алгоритмы v8::УФ 1cv8.cf Абонемент ($m)

Прочитав когда-то давно книжку "Разработка управляемых форм", составил для себя такую схемку-напоминалку для обращения в процессе разработки. С тех пор не раз выручала и избавляла от необходимости лезть в гуглы.

1 стартмани

29.06.2018    31619    stas_ganiev    26    

Демо связи веб сервисов 1С и php Промо

Практика программирования Математика и алгоритмы WEB v8 1cv8.cf Абонемент ($m)

Демонстрация обращения к веб сервису 1С из php. Пример простейший, уровня hello world. Дана одна страница и информационная база 1С с одним справочником и одним веб сервисом. Веб сервис выдаёт содержимое справочника по запросу странички.

1 стартмани

19.07.2013    32242    Трактор    20    

Принципы ООП в 1С (pattern Chain of responsibility)

Практика программирования v8 Абонемент ($m)

Данная статья является продолжением https://infostart.ru/public/850699, за основу будет применен тот же подход

1 стартмани

22.06.2018    6092    lazarenko    2    

Строим "фасады" в 1С

Практика программирования Математика и алгоритмы v8 Россия Абонемент ($m)

Как реализовать функционал, чтобы не было “мучительно больно” при расширении требований.

1 стартмани

04.05.2018    17636    ktb    41    

Случайность, совпадение, закономерность. Генератор случайных чисел

Практика программирования Математика и алгоритмы Игры v8 1cv8.cf Абонемент ($m)

Объект ГенераторСлучайныхЧисел удобно выдает случайные числа в заданном интервале значений. Исследование особенностей, рассуждения на тему случайных чисел, практика применения. Увлекательно в игровой форме можно исследовать работу генератора случайных чисел.

1 стартмани

20.01.2018    26823    Ликреонский    58    

115 полезностей от Буравова Андрея по курсу СКД Евгения Гилёва Промо

Математика и алгоритмы v8 1cv8.cf Россия Абонемент ($m)

Посмотрел 5,5 часовой курс по системе компоновки данных. Нашел невероятное количество не только необходимого, но и примеры не очевидного поведения СКД. У многих не хватает времени и терпения досмотреть курс до конца. Прочитав 115 полезностей, вы сможете понять в каком уроке освещен интересующий вас вопрос и быстро открыть его, чтобы посмотреть видео.

1 стартмани

08.04.2012    38835    Flashill    70    

Github и 1С. Пошаговая инструкция на конкретном примере

Математика и алгоритмы v8 Абонемент ($m)

Статья для тех, у кого есть неудержимое желание программировать и хочется доработать какую-то конфигурацию (или проект на 1С), выложенный на Github, но останавливают незнакомые слова Git, Github, Fork, Commit, Pull request, Merge, Issue.

1 стартмани

26.10.2017    44964    BlizD    51    

Планы обмена 1С: решение проблемы блокировок при помощи средств SQL Server

Практика программирования Математика и алгоритмы v8 Абонемент ($m)

Небольшое исследование возможности улучшить работу планов обмена 1С средствами SQL Server: view + triggers (представление + триггеры). В статье описывается один из приёмов SQL программирования для решения проблем блокировок, когда основные структуры данных изменить нельзя.

1 стартмани

10.01.2017    13109    zhichkin    4    

Степень сходства двух наименований справочника

Математика и алгоритмы v7.7 v8 Абонемент ($m)

Статья посвящена исследованию следующего вопроса: необходимо сравнить 2 наименования справочников с целью вычисления их степени сходства. По задумке, степень сходства должна выражаться в процентах.

1 стартмани

25.02.2015    20921    etmarket    43    

Технология создания коммерческих разработок на базе Базовой конфигурации "Управление Торговлей, ред.10.3" Промо

Математика и алгоритмы Рабочее место v8 v8::ОУ УТ10 УУ Абонемент ($m)

Создав однажды небольшую надстройку на базе конфигурации "УТ Базовая, ред.10.3", впоследствии разработка расширилась до неузнаваемости и приросла функционалом. Что удивительно, так это то, что разработка представляет собой внешнюю обработку вкупе со стандартными механизмами базовой версии, а значит не требует дополнительного конфигурирования БД. О том, как и что я реализовал, пойдет речь в данной статье.

1 стартмани

11.03.2012    25605    Rustig    93    

АЦРК: Многовариантный автоматический запрет редактирования (для конфигурации УТ 10.3)

Закрытие периода Математика и алгоритмы Администрирование данных 1С Закрытие периода v8 УТ10 Абонемент ($m)

В этой статье описывается усовершенствованная технология автоматической установки даты запрета редактирования Во-первых, можно определить несколько стратегий запрета редактирования с разными параметрами. Например, запрет в днях, запрет доступа в предыдущие месяцы кварталы и т.п., с указанием отступа от текущей даты. То есть для некоторых пользователей (рядовых менеджеров) при входе в базе будет устанавливаться запрет по вчерашний день, для других (старших менеджеров) на 5 дней назад, для третьих (администраторов базы или руководителей отдела) - запрет предыдущего месяца с отступом в 10 дней.. Во-вторых, запрет будет устанавливаться для ВСЕХ без исключения пользователей базы данных. Для самых привилегированных это будет максимальная глубина, но запрет будет установлен. Управление этой системой осуществляется через механизм дополнительных прав пользователей. При необходимости пользователь с полными правами может открыть для себя закрытый период, но только на текущий сеанс работы.

1 стартмани

22.07.2013    20902    acrk    9    

Разработка многоязычной системы

Математика и алгоритмы v8 Абонемент ($m)

В статье затронуты некоторые аспекты многоязычности системы с точки зрения их технической реализации

1 стартмани

20.06.2013    21034    YOr!k    54    

Передача аргумента, полученного по ComConnector, на сервер

Математика и алгоритмы v8 Абонемент ($m)

С точки зрения инкапсуляции, данные, переданные по COMConnector, следует обрабатывать в базе-приемнике. И тут возникает проблема, малопонятная для новичка из-за сложностей в отладке модуля внешнего соединения. Аргументы попросту не передаются в серверные модули.

1 стартмани

20.03.2013    6419    asved.ru    3    

Объектно-ориентированный взгляд на программирование в 1С

Математика и алгоритмы v8 1cv8.cf Абонемент ($m)

Рассматриваем программирование в 1С как работу с объектами и классами.

1 стартмани

18.04.2012    29070    BorisMor    241    

Использование нарастающих итогов в партионном учете и не только

Математика и алгоритмы v8 Россия Абонемент ($m)

Данный материал является иллюстрацией способов работы с запросами, использующими методику вычисления «нарастающих итогов». Также в данной статье рассматриваются вопросы практического использования запросов такого рода при партионном учете и расчете задолженностей. Фактически в данной статье рассматриваются альтернативы запросам, приведенным в статьях http://infostart.ru/public/61295/ и http://infostart.ru/public/68225/. Полный текст статьи можно также найти на http://nashe1c.ru/materials-view.jsp?id=383.

1 стартмани

25.08.2011    13921    y-str    107    

Модуль менеджера или статические методы класса?

Математика и алгоритмы v8 1cv8.cf Россия Абонемент ($m)

Зачем в платформе 8.2 добавили модуль менеджера объекта, как его использовать? Попробуем разобраться.

1 стартмани

02.07.2010    61186    zfilin    97    

Как я победил блокировки (deadlock)

Математика и алгоритмы v8 1cv8.cf Россия Абонемент ($m)

Статья о том, как сделать работу нормальной, комфортной для пользователей, в большой базе с большим количеством пользователей.

1 стартмани

28.09.2009    21753    Minotavrik    64