Другое название: Kit (инструментарий).

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

Задача. Рассмотрим инструментальную программу для создания пользовательского интерфейса, поддерживающего разные стандарты внешнего облика, например обычные прямоугольные элементы управления (Rect) и округлые (Round). Чтобы приложение можно было перенести на другой стандарт, в нем не должен быть жестко закодирован внешний облик элементов управления. Если инстанцирование классов для конкретного внешнего облика разбросано по всему приложению, то изменить облик впоследствии будет нелегко.

Решение. Паттерн Абстрактная Фабрика предлагает решить эту проблему, определив абстрактный класс ControlsFactory, в котором объявлен интерфейс для создания всех основных видов элементов управления (англ. – controls): окна (window), кнопки (button) и т.д. Есть также абстрактные классы для каждого отдельного вида и конкретные подклассы, реализующие элементы управления с определенным внешним обликом. В интерфейсе ControlsFactory имеется операция, возвращающая новый объект для каждого вида элемента. Клиенты вызывают эти операции для получения экземпляров элементов управления, но при этом ничего не знают о том, какие именно классы используют. Стало быть, клиенты остаются независимыми от выбранного стандарта внешнего облика.

 

(Для простоты понимания опущены зависимости, отраженные в комментариях)

 

Для каждого стандарта внешнего облика существует определенный подкласс ControlsFactory. Каждый такой подкласс реализует операции, необходимые для создания соответствующего стандарту элемента управления. Например, операция CreateButton в классе RectControlsFactory инстанцирует и возвращает стандартную прямоугольную кнопку, тогда как соответствующая операция в классе RoundControlsFactory возвращает округлую кнопку. Клиенты создают элементы управления, пользуясь исключительно интерфейсами ControlsFactory, Window и Button, и им ничего не известно о классах, реализующих элементы управления для конкретного стандарта. Другими словами, клиенты должны лишь придерживаться интерфейса, определенного абстрактным, а не конкретным классом.

Класс ControlsFactory также устанавливает зависимости между конкретными классами элементов управления. Округлое окно должно использовать округлые кнопки, текстовые поля и т.д., и это ограничение поддерживается автоматически, как следствие использования класса RoundControlsFactory.

Общая структура решения.


(Для простоты понимания опущены зависимости, отраженные в комментариях)

 

AbstractFactory (ControlsFactory) – абстрактная фабрика: объявляет интерфейс для операций, создающих абстрактные объекты-продукты.

CocreteFactoryY (RectControlsFactory, RoundControlsFactory) – конкретная фабрика: реализует операции, создающие конкретные объекты-продукты типа Y.

AbstractProductX (Window, Button) – абстрактные продукты: объявляют интерфейс для типов объектов-продуктов.

ConcreteProductXY (RectWindow, RoundButton и др.) – конкретные продукты: определяют объекты-продукты, создаваемые конкретной фабрикой Y, реализуя интерфейс AbstractProductX.

Client – клиент: пользуется исключительно интерфейсами, которые объявлены в классах AbstractFactory и AbstractProductX.

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

AbstractFactory передоверяет создание объектов-продуктов своим подклассам ConcreteFactoryY.

Применимость. Используйте паттерн Абстрактная Фабрика, когда:

Результаты. Паттерн Абстрактная Фабрика обладает следующими достоинствами и недостатками:

Особенности реализации. Вот некоторые полезные приемы реализации паттерна Абстрактная Фабрика.

Родственные паттерны.

Классы AbstractFactory почти всегда используют Фабричные Методы, но могут быть реализованы и с помощью паттерна Прототип.

Конкретная фабрика часто описывается паттерном Одиночка.