Абстрактная фабрика (Abstract factory)

Метафора

 

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

Как правило, одна фабрика занимается «производством» только одного рода «продуктов». Не рекомендуется «фабрику колы» создавать с учетом производства автомобильных покрышек. Как и в жизни, паттерн «фабрика» часто создается «одиночкой».

 

Назначение

 

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

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

  • Когда вектор изменения направлен на добавление новых продуктов, т.к. добавляя один метод для создания некоторого продукта, вам необходимо продублировать его на все фабрики;
  • Для создания не связанных объектов: бутылка колы и автомобиль, т.к. это усложняет понимание необходимости в такой фабрике.

Плюсы:

  • Фабрика гарантирует сочетаемость продуктов, так в бутылке из-под coca-cola вы не получите машинное масло (тут бутылка колы рассматривается как набор отдельных объектов: пластиковый контейнер и его наполнение);
  • Упрощение взаимозаменяемости семейства продуктов, Вы можете подменить одну фабрику на другую, при этом клиент будет оперировать новым семейством продуктов, т.к. внутри используются абстрактные интерфейсы. Конкретные классы изолируются внутри фабрик, клиенту о них знать не нужно;
  • Возможность расширить систему на новые фабрики не нарушая OCP принцип (SOLID).

 

Диаграмма

 

Абстрактная фабрика

Абстрактная фабрика

На данном рисунке мы видим некоторый класс Client, который работает с абстрактной фабрикой. Все конкретные фабрики наследуются от абстрактной фабрики (AbstractFactory), абстрактная фабрика создает некие абстрактные продукты. Конкретные фабрики решают, какие конкретные продукты они будут создавать. Клиент во время исполнения снабжается той или иной реализацией абстрактной фабрики.

 

Пример

 

В данном примере и далее по ходу статьи нет отдельного класса клиента, вся работа с шаблонами происходит непосредственно в программе:

В нашем примере фабрика создается непосредственно в коде программы, однако в реальных программах заранее определить нужную фабрику может быть невозможно. Решается это за счёт динамического создания фабрики, класс которой определен из настроек, где-нибудь в кластере ракурсов, при этом настройка эта считывается в еще одном классе, который служит своего рода фабрикой фабрик.

Видео