Abstract Factory
Abstract Factory — породжуючий патерн, що створює сімейство повʼязаних обʼєктів без привʼязки до їхніх конкретних класів. Клієнт отримує фабрику і через неї будує узгоджений набір обʼєктів, які гарантовано сумісні один з одним.
Метафора
Section titled “Метафора”Меблева серія «Сканді»: крісло, диван, стіл — усі в одному стилі. Ти купуєш не окремі меблі, а «сімейство»: замовив в одній фабриці — отримав узгоджений комплект. Інша фабрика видає «Класику»: інше крісло, інший диван, інший стіл — але теж узгоджені між собою.
Коли застосовувати
Section titled “Коли застосовувати”- Треба створювати кілька типів продуктів, які мають бути сумісні всередині однієї групи.
- Треба перемикати цілу групу разом (тема UI: dark/light; БД-діалект: Oracle/HANA; мова документів: UA/EN).
- Клієнтський код не повинен знати конкретні класи — він працює з інтерфейсами фабрики й інтерфейсами продуктів.
Відмінність від Factory Method
Section titled “Відмінність від Factory Method”| Factory Method | Abstract Factory | |
|---|---|---|
| Скільки продуктів | Один тип | Кілька типів, повʼязаних між собою |
| Скільки реалізацій | Одна фабрика, багато продуктів | Багато фабрик, кожна видає свій набір |
| Приклад | Парсер JSON чи XML | UI-тема: кнопки + поля + діалоги для dark/light |
ABAP-реалізація
Section titled “ABAP-реалізація”Приклад: звіти для різних регіонів. Кожен регіон має свої правила форматування дат, валют і заголовків — і всі три мають узгоджуватись.
" Інтерфейси продуктів — що робить кожен компонентINTERFACE zif_date_formatter. METHODS format IMPORTING iv_date TYPE d RETURNING VALUE(rv_text) TYPE string.ENDINTERFACE.
INTERFACE zif_currency_formatter. METHODS format IMPORTING iv_amount TYPE p iv_currency TYPE waers RETURNING VALUE(rv_text) TYPE string.ENDINTERFACE.
INTERFACE zif_header_builder. METHODS build RETURNING VALUE(rv_text) TYPE string.ENDINTERFACE.
" Абстрактна фабрика — контракт сімействаINTERFACE zif_locale_factory. METHODS: create_date_formatter RETURNING VALUE(ro) TYPE REF TO zif_date_formatter, create_currency_formatter RETURNING VALUE(ro) TYPE REF TO zif_currency_formatter, create_header_builder RETURNING VALUE(ro) TYPE REF TO zif_header_builder.ENDINTERFACE.
" Конкретна фабрика для EU (DD.MM.YYYY, EUR, німецькі заголовки)CLASS zcl_locale_factory_eu DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_locale_factory.ENDCLASS.
CLASS zcl_locale_factory_eu IMPLEMENTATION. METHOD zif_locale_factory~create_date_formatter. ro = NEW zcl_date_formatter_eu( ). ENDMETHOD. METHOD zif_locale_factory~create_currency_formatter. ro = NEW zcl_currency_formatter_eu( ). ENDMETHOD. METHOD zif_locale_factory~create_header_builder. ro = NEW zcl_header_builder_eu( ). ENDMETHOD.ENDCLASS.
" Аналогічно zcl_locale_factory_us, zcl_locale_factory_uaВикористання:
DATA lo_factory TYPE REF TO zif_locale_factory.
CASE p_region. WHEN 'EU'. lo_factory = NEW zcl_locale_factory_eu( ). WHEN 'US'. lo_factory = NEW zcl_locale_factory_us( ). WHEN 'UA'. lo_factory = NEW zcl_locale_factory_ua( ).ENDCASE.
" Далі код НЕ знає про конкретний регіон:DATA(lv_date) = lo_factory->create_date_formatter( )->format( sy-datum ).DATA(lv_amount) = lo_factory->create_currency_formatter( )->format( iv_amount = 1000 iv_currency = 'EUR' ).DATA(lv_header) = lo_factory->create_header_builder( )->build( ).Гарантія: усі три виклики повертають обʼєкти одного регіону — не сплутаєш німецький формат дат з доларовою валютою.
SAP-специфіка
Section titled “SAP-специфіка”cl_abap_typedescr+cl_abap_structdescr+cl_abap_tabledescr— сімейство описів типів, отримується через фабрикуcl_abap_typedescr=>describe_by_*.- Кастомні output-processors (Smart Forms, Adobe Forms, SAP Script) — кандидати на Abstract Factory, коли треба рендерити в усіх трьох форматах за єдиним контрактом.
- Конвенція: для кожного регіонального customizing-блоку робити окрему фабрику, не
IF p_region = 'EU'по всьому коду.
Підводні камені
Section titled “Підводні камені”- Вибух класів. Abstract Factory додає: інтерфейс фабрики + інтерфейси кожного продукту + по одному конкретному класу на (фабрика × продукт). 3 фабрики × 3 продукти = 12+ класів. Застосовуй, коли продуктів дійсно кілька і вони мають бути узгоджені.
- Додавання нового продукту = правка всіх фабрик. Якщо часто додаєш нові типи продуктів — Abstract Factory стає болючим. Якщо часто додаєш нові сімейства — зручно. Вибирай вісь варіативності.
- Не ховай вибір фабрики глибоко. Фабрику обирають один раз нагорі (наприклад, у
controller->gc_initialization) і пробрасують вниз як DI — щоб тестувати з фейковою фабрикою.
Коли НЕ використовувати
Section titled “Коли НЕ використовувати”- Продукт один. Бери Factory Method.
- Продукти не повʼязані між собою. Кілька окремих фабрик краще за одну Abstract Factory, що навʼязує штучну групу.
- Сімейства продуктів розширюються частіше, ніж самі продукти — Abstract Factory погано масштабується на нові типи продуктів.