Патерн (шаблон) проектування abstract factory (абстрактна фабрика)

Призначення паттерна Abstract Factory

Використовуйте патерн Abstract Factory (абстрактна фабрика) якщо:

Наведемо приклади груп взаємопов'язаних об'єктів.

Нехай деякий додаток з підтримкою графічного інтерфейсу користувача розраховане на використання на різних платформах, при цьому зовнішній вигляд цього інтерфейсу повинен відповідати прийнятому стилю для тієї чи іншої платформи. Наприклад, якщо це програма встановлена ​​на Windows-платформу, то його кнопки, меню, смуги прокрутки повинні відображатися в стилі, прийнятому для Windows. Групою взаємопов'язаних об'єктів в цьому випадку будуть елементи графічного інтерфейсу користувача для конкретної платформи.

І останній приклад. У розділі породжують патерни говорилося про гру-стратегії, в якій описується військове протистояння між арміями Риму і Карфагена. Очевидно, що зовнішній вигляд, бойові порядки і характеристики для різних родів військ (піхота, лучники, кіннота) в кожній армії будуть своїми. В даному випадку сімейством взаємопов'язаних об'єктів будуть всі види воїнів для тієї чи іншої протиборчої сторони, при цьому повинна виключатися, наприклад, така ситуація, коли римська кіннота воює на боці Карфагена.

Опис паттерна Abstract Factory

Патерн Abstract Factory реалізується на основі фабричних методів (див. Патерн Factory Method).

Будь-яке сімейство або група взаємопов'язаних об'єктів характеризується кількома загальними типами створюваних продуктів, при цьому самі продукти таких типів будуть різними для різних сімейств. Наприклад, для випадку стратегічної гри загальними типами створюваних продуктів будуть піхота, лучники і кіннота, при цьому кожен з цих родів військ римської армії може істотно відрізнятися за зовнішнім виглядом і бойовими характеристиками від соответствуюших родів військ армії Карфагена.

Для того щоб система залишалася незалежною від специфіки того чи іншого сімейства продуктів необхідно використовувати загальні інтерфейси для всіх основних типів продуктів. У разі стратегічної гри це означає, що необхідно використовувати три абстрактних базових класу для кожного типу воїнів: піхоти, лучників і кінноти. Похідні від них класи будуть реалізовувати специфіку відповідного типу воїнів тієї чи іншої армії.

UML-діаграма класів паттерна Abstract Factory

Патерн (шаблон) проектування abstract factory (абстрактна фабрика)

Реалізація патерну Abstract Factory

Наведемо реалізацію паттерна Abstract Factory для військової стратегії "Пунічні війни". При цьому передбачається, що число і типи створюваних на початку гри бойових одиниць ідентичні для обох армій. Детальний опис цієї гри можна знайти в розділі Що породжують патерни.

Висновок програми буде наступним:

Результати застосування патерну Abstract Factory

Переваги паттерна Abstract Factory

  • Приховує сам процес породження об'єктів, а також робить систему незалежною від типів створюваних об'єктів, специфічних для різних сімейств або груп (користувачі оперують цими об'єктами через відповідні абстрактні інтерфейси).
  • Дозволяє швидко налаштовувати систему на потрібну сімейство створюваних об'єктів. У разі многоплатформенного графічного додатку для переходу на нову платформу, тобто для заміни графічних елементів (кнопок, меню, смуг прокрутки) одного стилю іншим досить створити потрібний підклас абстрактної фабрики. При цьому умова неможливості одночасного використання елементів різних стилів для деякої платформи буде виконано автоматично.

Недоліки паттерна Abstract Factory

  • Важко додавати нові типи створюваних продуктів або замінювати існуючі, так як інтерфейс базового класу абстрактної фабрики фіксований. Наприклад, якщо для нашої стратегічної гри потрібно буде ввести новий вид військової одиниці - облогові знаряддя, то треба буде додати новий фабричний метод, оголосивши його інтерфейс в полиморфном базовому класі AbstractFactory і реалізувавши в усіх підкласах. Зняти це обмеження можна наступним чином. Всі створювані об'єкти повинні наслідувати від загального абстрактного базового класу, а в єдиний фабричний метод як параметр необхідно передавати ідентифікатор типу об'єкта, який потрібно створити. Однак в цьому випадку необхідно враховувати наступний момент. Фабричний метод створює об'єкт запитаного підкласу, але при цьому повертає його з інтерфейсом загального абстрактного класу у вигляді посилання або покажчика, тому для такого об'єкта буде важко виконати будь-яку операцію, специфічну для підкласу.