Абстрактная фабрика (Abstract Factory)
реализации: java, количество: 15
реализации(исходники)
+добавить
Имя
«Паттерн Abstract Factory»
Абстрактная фабрика – паттерн, порождающий объекты источник codelab.ru оригинал codelab.ru
Условия, Задача, Назначение
Предоставляет интерфейс для создания группы объектов, бизнес объектов участников всей системы, использующихся далее в рамках всего приложения. Смысл в том, что их конкретные классы не объявляются, позволяя, таким образом, легко заменять их в дальнейшем, как отдельные объекты так и все взаимосвязанное семейство.
Мотивация
Рассмотрим инструментальную программу для создания пользовательского интерфейса, поддерживающего разные стандарты внешнего облика, например Motif и Presentation Manager.
codelab.ru источник codelab.ru оригинал
Внешний облик определяет визуальное представление и поведение элементов пользовательского интерфейса («виджетов») – полос прокрутки, окон и кнопок. Чтобы приложение можно было перенести на другой стандарт, в нем не должен быть жестко закодирован внешний облик виджетов. Если инстанцирование классов для конкретного внешнего облика разбросано по всему приложению, то изменить облик впоследствии будет нелегко. codelab.ru источник codelab.ru оригинал
Мы можем решить эту проблему, определив абстрактный класс WidgetFactory, в котором объявлен интерфейс для создания всех основных видов виджетов. Есть также абстрактные классы для каждого отдельного вида и конкретные под-классы, реализующие виджеты с определенным внешним обликом. В интерфейсе WidgetFactory имеется операция, возвращающая новый объект-виджет для каждого абстрактного класса виджетов. Клиенты вызывают эти операции для получения экземпляров виджетов, но при этом ничего не знают о том, какие именно классы используют. Стало быть, клиенты остаются независимыми от выбранного стандарта внешнего облика. codelab.ru codelab.ru источник оригинал
Для каждого стандарта внешнего облика существует определенный подкласс WidgetFactory. Каждый такой подкласс реализует операции, необходимые для создания соответствующего стандарту виджета. Например, операция CreateScrollBar в классе MotifWidgetFactory инстанцирует и возвращает полосу прокрутки в стандарте Motif, тогда как соответствующая операция в классе PMWidgetFactory возвращает полосу прокрутки в стандарте Presentation Manager. Клиенты создают виджеты, пользуясь исключительно интерфейсом WidgetFactory, и им ничего не известно о классах, реализующих виджеты для конкретного стандарта. Другими словами, клиенты должны лишь придерживаться интерфейса, определенного абстрактным, а не конкретным классом. codelab.ru источник codelab.ru оригинал
Признаки применения, использования паттерна Абстрактная фабрика (Abstract Factory)
Если:- Система не должна зависеть от того, как создаются, компонуются и представляются входящие объекты. Объекты, построенные определенным образом, просто как бы подаются на вход. источник codelab.ru codelab.ru оригинал
- Конкретный вариант требуемого поведения системы дают не отдельные объекты, а четко выраженное семейство связанных объектов. Объекты одного семейства должны использоваться вместе. codelab.ru источник codelab.ru оригинал
- Для функционирования системы необходимо одно из таким семейств взаимосвязанных объектов. Иными словами, на вход системы подается только целое семейство таких объектов, система конфигурируется одним из семейств. codelab.ru оригинал codelab.ru источник
- Соблюдаются некоторые условия конфиденциальности, когда не желательно предоставлять весь api библиотеки объектов, их реализацию, вместо этого – только их интерфейсы. оригинал codelab.ru источник codelab.ru
Решение
оригинал codelab.ru источник codelab.ru
Участники паттерна Абстрактная фабрика (Abstract Factory)
- AbstractFactory (WidgetFactory) - абстрактная фабрика.
Объявляет общий интерфейс для операций создания абстрактных объектов – продуктов. Далее в приложении вместо абстрактных будут создаваться уже конкретные объекты какого-либо одного семейство. оригинал codelab.ru источник codelab.ru - ConcreteFactory[N] (Motif WidgetFactory, PMWidgetFactory) – конкретная фабрика(класс).
Определяет, реализует операции, создающие все объекты одного конкретного семейства. codelab.ru codelab.ru оригинал источник - AbstractProduct[A-Z] (Window, ScrollBar) – абстрактный продукт(класс).
Определяет общий интерфейс для типа объекта-продукта. A-Z в данном случае – множество таких продуктов, составляющих абстрактное семейство. источник codelab.ru оригинал codelab.ru - ConcreteProduct[A-Z][N] (Motif Window, Motif ScrollBar) - конкретный продукт(класс). Определяет конкретный объект-продукт типа [A-Z], создаваемый соответствующей конкретной фабрикой [N]. оригинал источник codelab.ru codelab.ru
- Client – клиент.
Другой программный модуль, фрагмент кода, дающий команды на получение конкретного семейства продуктов, пользуясь только известными интерфейсами классов AbstractFactory и AbstractProduct.
codelab.ru оригинал источник codelab.ru
Схема использования паттерна Абстрактная фабрика (Abstract Factory)
Клиент(Client) создает единственный экземпляр ConcreteFactory, с помощью которого получает когда ему нужно все объекты соответствующего семейства. Поэтому для создания других объектов, выполняющих те же функции как-нибудь несколько иным способом, нужно лишь инстанцировать, создать другую ConcreteFactory. источник оригинал codelab.ru codelab.ru
Вопросы, касающиеся реализации паттерна Абстрактная фабрика (Abstract Factory)
- Абстрактная фабрика – синглтон.
В общем случае приложению нужен лишь 1 экземпляр конкретной фабрики для каждого семейства продуктов, поэтому очень уместно применить здесь паттерн Одиночка(singleton) оригинал codelab.ru codelab.ru источник - Фабричный метод для создания каждого продукта.
Класс AbstractFactory объявляет только интерфейс для создания продуктов. Фактическое их создание - дело подклассов ConcreteProduct. Чаще всего для этой цели определяется фабричный метод для каждого продукта (см. паттерн фабричный метод). Конкретная фабрика специфицирует свои продукты путем замещения фабричного метода для каждого из них. Хотя такая реализация проста, она требует создавать новый подкласс конкретной фабрики для каждого семейства продуктов, даже если они почти ничем не отличаются.
Если семейств продуктов может быть много, то конкретную фабрику удастся реализовать с помощью паттерна прототип. В этом случае она инициализируется экземпляром-прототипом каждого продукта в семействе и создает новый продукт путем клонирования этого прототипа. Подход на основе прототипов устраняет необходимость создавать новый класс конкретной фабрики для каждого нового семейства продуктов. codelab.ru источник codelab.ru оригинал - Определение расширяемых фабрик.
Класс AbstractFactory обычно определяет разные операции для каждого вида изготавливаемых продуктов. Виды продуктов кодируются в сигнатуре операции. Для добавления нового вида продуктов нужно изменить интерфейс класса AbstractFactory и всех зависящих от него классов.
Более гибкий, но не такой безопасный способ - добавить параметр к операциям, создающим объекты. Данный параметр определяет вид создаваемого объекта. Это может быть идентификатор класса, целое число, строка или что-то еще, однозначно описывающее вид продукта. При таком подходе классу AbstractFactory нужна только одна операция Make с параметром, указывающим тип создаваемого объекта. (Данный прием применялся в обсуждавшихся выше абстрактных фабриках на основе прототипов и классов. Такой вариант проще использовать в динамически типизированных языках вроде Smalltalk, нежели в статически типизированных, каким является C++. Воспользоваться им в C++ можно только, если у всех объектов имеется общий абстрактный базовый класс или если объекты-продукты могут быть безопасно приведены к корректному типу клиентом, который их запросил. В разделе «Реализация» из описания паттерна фабричный метод показано, как реализовать такие параметризованные операции в C++. Но даже если приведение типов не нужно, остается принципиальная проблема: все продукты возвращаются клиенту одним и тем же абстрактным интерфейсом с уже определенным типом возвращаемого значения. Клиент не может ни различить классы продуктов, ни сделать какие-нибудь предположения о них. Если клиенту нужно выполнить операцию, зависящую отподкласса, то она будет недоступна через абстрактный интерфейс. Хотя клиент мог бы выполнить динамическое приведение типа (например, с помощью оператора dynamic_cas t в C++), это небезопасно и необязательно заканчивается успешно. Здесь мы имеем классический пример компромисса между высокой степенью гибкости и расширяемостью интерфейса) codelab.ru оригинал источник codelab.ru
Результаты
Достоинства и недостатки паттерна абстрактная фабрика. Достоинства: codelab.ru codelab.ru оригинал источник
- Скрываются реализации конкретных классов.
Помогает контролировать классы объектов, создаваемых приложением. Т.е. вы остаетесь совершенно свободны от клиента в вопросе создания конкретных объектов – фабрика изолирует клиента от деталей реализации классов. Она также инкапсулирует ответственность за создание классов и сам процесс их создания. Клиенту известны лишь интерфейсы абстрактных классов, которыми через которые он только и может выполнять дальше свою бизнес логику с созданным семейством объектов. Классы отдаваемых вовне семейства объекты – известны лишь конкретной фабрике, поэтому дальше они ни в клиенте, ни в остальных частях приложения – не встречаются. оригинал источник codelab.ru codelab.ru - Свободная замена семейства продуктов.
Класс конкретной фабрики появляется в приложении только один раз: при инстанцировании. Это облегчает замену используемой приложением конкретной фабрики. Приложение может изменить конфигурацию продуктов, просто подставив новую конкретную фабрику. Поскольку абстрактная фабрика создает все семейство продуктов, то и заменяется сразу все семейство. В нашем примере пользовательского интерфейса перейти от виджетов Motif к виджетам Presentation Manager можно, просто переключившись на продукты соответствующей фабрики и заново создав интерфейс. codelab.ru источник оригинал codelab.ru - Гарантия использования только одного вида продуктов
Если продукты некоторого семейства спроектированы для совместного использования, то важно, чтобы приложение в каждый момент времени работало только с продуктами единственного семейства. Класс AbstractFactory позволяет легко соблюсти это ограничение; codelab.ru codelab.ru оригинал источник
Один из основных архитектурных недостатков – почти невозможно расширить семейство продуктов в дальнейшем. Можно сказать, что это также сложно, как и расширять интерфейс после более-менее продолжительного развития системы на его основе. Интерфейс AbstractFactory фиксирует набор продуктов, которые можно создать. Для поддержки новых продуктов необходимо расширить интерфейс фабрики, то есть изменить класс AbstractFactory и все его подклассы. codelab.ru источник оригинал codelab.ru
Пример
factory=ru
carNum=10
truckNum=2
busNum=4
оригинал источник codelab.ru codelab.ru
factory=us
carNum=15
truckNum=4
busNum=2
codelab.ru источник codelab.ru оригинал
Известные применения паттерна Абстрактная фабрика (Abstract Factory)
оригинал codelab.ru источник codelab.ruРодственные паттерны
источник оригинал codelab.ru codelab.ruРеализации: java(15) +добавить реализацию
1) Car.java, code #400[автор:this]
2) Truck.java, code #401[автор:this]
3) Bus.java, code #402[автор:this]
4) Kamaz.java, code #404[автор:this]
5) Liaz.java, code #405[автор:this]
6) Vaz2110.java, code #406[автор:this]
7) RusFleetFactory.java, code #410[автор:this]
8) CityJet.java, code #407[автор:this]
9) Dodge.java, code #408[автор:this]
10) GeneralMotorsTruck.java, code #409[автор:this]
11) AmericanFleetFactory.java, code #411[автор:this]
12) FleetRun.java, code #403[автор:this]
13) MixedFleetFactory.java, code #412[автор:this]
14) FleetFactory.java, code #413[автор:this]
15) Fleet, code #613[аноним:XoLmC]



