Chat
Ask me anything
Ithy Logo
Sign in to save

Как "Фабричный метод" революционизирует создание объектов в 1С: Подробный разбор с примерами

Узнайте, как этот мощный паттерн проектирования упрощает разработку, повышает гибкость и облегчает поддержку ваших 1С-решений.

factory-method-pattern-1c-example-2t14vc6o

Ключевые моменты

  • Централизация создания объектов: Паттерн "Фабричный метод" позволяет делегировать логику создания объектов специальному методу, избавляя клиентский код от необходимости знать конкретные классы создаваемых экземпляров.
  • Повышенная гибкость и расширяемость: Добавление новых типов продуктов (объектов) не требует изменения существующего клиентского кода, который использует фабрику. Достаточно модифицировать или расширить саму фабрику.
  • Адаптация для 1С: В 1С, где классическое наследование отличается от языков типа Java или C#, "Фабричный метод" эффективно реализуется через общие модули и их экспортные функции, сохраняя все преимущества паттерна.

Введение в паттерн "Фабричный метод" в экосистеме 1С

Паттерн "Фабричный метод" (Factory Method) – это один из порождающих паттернов проектирования, который предоставляет интерфейс для создания объектов в суперклассе, но позволяет подклассам изменять тип создаваемых объектов. В контексте 1С, где традиционное наследование классов имеет свои особенности, этот паттерн адаптируется для упрощения процесса создания экземпляров различных объектов, таких как документы, элементы справочников или отчеты, без жесткой привязки клиентского кода к их конкретным типам.

Основная идея заключается в том, чтобы инкапсулировать логику выбора и создания конкретного объекта. Вместо того чтобы клиентский код напрямую вызывал конструктор объекта (например, Новый ДокументОбъект.РеализацияТоваровУслуг), он обращается к "фабричному" методу, передавая ему параметры, на основе которых фабрика решает, какой именно объект создать и вернуть. Это делает систему более гибкой и легко расширяемой.

Диаграмма паттерна Фабричный метод

Общая UML-диаграмма паттерна "Фабричный метод", иллюстрирующая взаимосвязь Создателя, Конкретных Создателей и Продуктов.

Зачем использовать "Фабричный метод" в 1С?

Применение "Фабричного метода" в 1С обусловлено стремлением к улучшению архитектуры конфигураций, особенно в крупных и сложных системах. Ключевые преимущества включают:

  • Уменьшение связанности: Клиентский код зависит только от общего интерфейса (или ожидаемого поведения) продукта и интерфейса фабрики, а не от конкретных классов создаваемых объектов. Это упрощает замену или добавление новых типов продуктов.
  • Централизация логики создания: Вся логика по выбору и инстанцированию объектов сосредоточена в одном месте – фабричном методе. Если правила создания меняются, изменения вносятся только в фабрику.
  • Следование принципу открытости/закрытости: Систему можно расширять (добавлять новые типы продуктов и их создателей) без модификации существующего кода, который уже использует фабрику.
  • Упрощение кода: Клиентский код становится чище, так как из него уходит сложная условная логика, связанная с выбором типа создаваемого объекта.

В 1С, где часто приходится работать с динамическим созданием различных типов документов, отчетов или обработок в зависимости от настроек, данных или бизнес-логики, "Фабричный метод" становится весьма полезным инструментом.


Структура и компоненты паттерна

Классический паттерн "Фабричный метод" включает следующие основные компоненты:

  • Продукт (Product): Определяет интерфейс объектов, которые создает фабричный метод. В 1С это может быть общий набор ожидаемых методов или свойств для создаваемых объектов (например, документов определенного вида).
  • Конкретный Продукт (ConcreteProduct): Реализует интерфейс Продукта. Это конкретные классы объектов, которые будут создаваться (например, ДокументОбъект.ПоступлениеТоваровУслуг, ДокументОбъект.ЗаказКлиента).
  • Создатель (Creator): Объявляет фабричный метод, который возвращает объект типа Продукт. Создатель также может определять реализацию по умолчанию для фабричного метода. В 1С роль Создателя часто выполняет общий модуль.
  • Конкретный Создатель (ConcreteCreator): Переопределяет фабричный метод для возврата экземпляра Конкретного Продукта. В 1С логика различных "Конкретных Создателей" может быть инкапсулирована внутри одного фабричного метода в общем модуле с использованием условных конструкций.

Визуализация структуры паттерна "Фабричный метод"

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

mindmap root["Фабричный метод в 1С"] id1["Создатель (Creator)
(Общий модуль)"] id1_1["ФабричныйМетод(параметры): Объект"] id1_1_1["Логика выбора и создания
Конкретного Продукта"] id2["Продукт (Product)
(Ожидаемый интерфейс/поведение объекта)"] id2_1["Общие методы/свойства
(например, Записать(), Провести())"] id3["Конкретный Продукт A
(ДокументОбъект.ТипА)"] id3_1["Реализация интерфейса Продукта"] id4["Конкретный Продукт B
(ДокументОбъект.ТипБ)"] id4_1["Реализация интерфейса Продукта"] id5["Клиентский код"] id5_1["Вызывает ФабричныйМетод()"] id5_2["Работает с объектом через интерфейс Продукта"]

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


Пример реализации "Фабричного метода" в 1С

Рассмотрим практический пример. Предположим, нам необходимо создавать различные типы документов ("ЗаказПокупателя", "РеализацияТоваровУслуг") в зависимости от некоторого условия или параметра. Мы можем реализовать фабричный метод в общем модуле.

Общий модуль: УправлениеДокументамиФабрика


// Общий модуль: УправлениеДокументамиФабрика
// Серверный, вызов сервера

// Функция выступает в роли Фабричного Метода
// @ПараметрыСоздания - Структура, может содержать ТипДокумента, Основание и др.
// @Возвращаемое значение - ДокументОбъект.<ИмяДокумента> или Неопределено
Функция СоздатьДокументПоПараметрам(Знач ПараметрыСоздания) Экспорт
    
    Перем НовыйДокумент;
    
    Если НЕ ПараметрыСоздания.Свойство("ТипДокумента") Тогда
        // Можно вызвать исключение или вернуть Неопределено
        Сообщить("Не указан тип документа для создания!");
        Возврат Неопределено;
    КонецЕсли;
    
    ТипЗапрашиваемогоДокумента = ПараметрыСоздания.ТипДокумента;
    
    Если ТипЗапрашиваемогоДокумента = "ЗаказПокупателя" Тогда
        НовыйДокумент = Документы.ЗаказКлиента.СоздатьДокумент();
        // Дополнительная инициализация специфичная для ЗаказаКлиента
        НовыйДокумент.Дата = ТекущаяДатаСеанса();
        Если ПараметрыСоздания.Свойство("Контрагент") Тогда
            НовыйДокумент.Контрагент = ПараметрыСоздания.Контрагент;
        КонецЕсли;
        // ... другие поля ...

    ИначеЕсли ТипЗапрашиваемогоДокумента = "РеализацияТоваровУслуг" Тогда
        НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
        // Дополнительная инициализация специфичная для Реализации
        НовыйДокумент.Дата = ТекущаяДатаСеанса();
        Если ПараметрыСоздания.Свойство("Контрагент") Тогда
            НовыйДокумент.Контрагент = ПараметрыСоздания.Контрагент;
        КонецЕсли;
        Если ПараметрыСоздания.Свойство("Договор") Тогда
            НовыйДокумент.ДоговорКонтрагента = ПараметрыСоздания.Договор;
        КонецЕсли;
        // ... другие поля ...
        
    // Можно добавить другие типы документов
    // ИначеЕсли ТипЗапрашиваемогоДокумента = "ПоступлениеТоваровУслуг" Тогда
    //     НовыйДокумент = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();
    //     // ...
        
    Иначе
        Сообщить("Создание документов типа '" + ТипЗапрашиваемогоДокумента + "' не поддерживается фабрикой.");
        Возврат Неопределено;
    КонецЕсли;
    
    // Общая логика для всех создаваемых документов, если есть
    Если НовыйДокумент <> Неопределено И ПараметрыСоздания.Свойство("Ответственный") Тогда
        НовыйДокумент.Ответственный = ПараметрыСоздания.Ответственный;
    КонецЕсли;
        
    Возврат НовыйДокумент;
    
КонецФункции
    

Пример использования фабрики в клиентском коде (например, в модуле формы)


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

&НаКлиенте
Процедура СоздатьРеализацию(Команда)
    ПараметрыДляФабрики = Новый Структура;
    ПараметрыДляФабрики.Вставить("ТипДокумента", "РеализацияТоваровУслуг");
    ПараметрыДляФабрики.Вставить("Контрагент", СсылкаНаКонтрагента);
    ПараметрыДляФабрики.Вставить("Договор", СсылкаНаДоговор); // Предположим, СсылкаНаДоговор определена
    ПараметрыДляФабрики.Вставить("Ответственный", ПараметрыСеанса.ТекущийПользователь);

    СоздатьДокументНаСервере(ПараметрыДляФабрики);
КонецПроцедуры

&НаСервереБезКонтекста
Процедура СоздатьДокументНаСервере(ПараметрыДляФабрики)
    НовыйДокумент = УправлениеДокументамиФабрика.СоздатьДокументПоПараметрам(ПараметрыДляФабрики);
    
    Если НовыйДокумент <> Неопределено Тогда
        // Дальнейшая работа с документом, например, открытие его формы
        // ЗначениеВДанныеФормы(НовыйДокумент, ИмяРеквизитаФормы); // если нужно отобразить на форме
        Сообщить("Документ '" + НовыйДокумент.Метаданные().Синоним + "' успешно создан фабрикой.");
        // ОткрытьФорму("Документ." + НовыйДокумент.Метаданные().Имя + ".ФормаОбъекта", Новый Структура("Ключ", НовыйДокумент.Ссылка));
        // Для примера просто выведем сообщение
    Иначе
        Сообщить("Не удалось создать документ через фабрику.");
    КонецЕсли;
КонецПроцедуры
    

В этом примере функция СоздатьДокументПоПараметрам в общем модуле УправлениеДокументамиФабрика является фабричным методом. Клиентский код (процедуры СоздатьЗаказКлиента и СоздатьРеализацию) просто вызывает эту функцию, передавая ей тип желаемого документа и другие необходимые параметры, не вдаваясь в детали его непосредственного создания и начальной инициализации.


Сравнение подходов: Фабричный метод vs Прямое создание объектов в 1С

Чтобы наглядно оценить преимущества и компромиссы использования паттерна "Фабричный метод" по сравнению с традиционным прямым созданием объектов в коде 1С, рассмотрим диаграмму сравнения по нескольким ключевым аспектам. Оценка производится по шкале от 1 (низкий) до 10 (высокий).

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


Таблица компонентов паттерна в 1С

Для наглядности сведем компоненты паттерна "Фабричный метод" и их типичные реализации в среде 1С в таблицу.

Компонент паттерна (Классический) Аналог/Реализация в 1С Описание в контексте 1С
Product (Продукт) Общий ожидаемый интерфейс или тип объекта (например, ДокументОбъект, ОтчетОбъект) Определяет набор методов и свойств, которые клиент ожидает от создаваемого объекта. Явный интерфейс может отсутствовать, но подразумевается общее поведение.
ConcreteProduct (Конкретный Продукт) Конкретный тип объекта 1С (например, Документы.ЗаказКлиента.СоздатьДокумент(), Отчеты.Продажи.Создать()) Конкретная реализация создаваемого объекта.
Creator (Создатель) Общий модуль Модуль, содержащий фабричный метод. Он определяет интерфейс для создания продуктов.
ConcreteCreator (Конкретный Создатель) Логика внутри экспортной функции общего модуля (фабричного метода) В 1С часто не создаются отдельные "классы" создателей. Вместо этого, одна фабричная функция в общем модуле содержит условную логику (Если...Тогда...ИначеЕсли) для создания различных конкретных продуктов.
FactoryMethod (Фабричный метод) Экспортная функция в общем модуле Функция, которая принимает параметры и на их основе решает, какой конкретный продукт создать и вернуть.
Client (Клиент) Любой код (модуль формы, модуль объекта, другой общий модуль), который нуждается в создании объекта Использует фабричный метод для получения экземпляра продукта, не зная о его конкретном типе.

Видео "Design Patterns в 1С. Рассматриваем и пробуем ..." - отличное введение в тему паттернов проектирования в контексте 1С, включая концепции, схожие с фабричным методом.

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


Часто задаваемые вопросы (FAQ)

В чем отличие "Фабричного метода" от "Абстрактной фабрики" в 1С?

"Фабричный метод" — это паттерн, который определяет интерфейс для создания одного объекта, но позволяет подклассам (или в 1С — различным веткам логики в одном методе) решать, какой конкретно объект создать. Он фокусируется на создании одного типа продукта.

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

Обязательно ли использовать наследование для "Фабричного метода" в 1С?

Нет, не обязательно. Хотя классическое определение паттерна часто упоминает наследование (Creator и ConcreteCreator), в 1С его принципы успешно реализуются без формального наследования классов в стиле Java или C#. Чаще всего используется один общий модуль, содержащий экспортную функцию (фабричный метод). Различные "конкретные создатели" эмулируются через условные операторы (Если...Тогда...ИначеЕсли) внутри этой функции, которые выбирают, какой тип объекта инстанцировать на основе входных параметров. Главное — делегирование создания объекта специализированному методу.

Когда не стоит использовать "Фабричный метод"?

Паттерн "Фабричный метод" может быть избыточным в следующих случаях:

  • Простые сценарии: Если у вас всего один-два типа объектов, и логика их создания проста и не планируется к частому изменению или расширению, введение фабрики может неоправданно усложнить код.
  • Низкая вероятность изменений: Если классы создаваемых объектов и логика их инстанцирования стабильны и вряд ли изменятся в будущем.
  • Производительность в критических участках: Хотя обычно накладные расходы на вызов дополнительного метода невелики, в очень высоконагруженных и критичных к производительности участках кода каждый дополнительный вызов может иметь значение. Однако, это редкий случай, и обычно преимущества в гибкости перевешивают.

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


Рекомендуемые запросы для дальнейшего изучения


Источники и полезные ссылки


Last updated May 7, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI
Download Article
Delete Article