CodeLAB
на главную карта сайта обратная связь
каталог | задачи | паттерны | исходники | стат | форумы | ссылки
 гость
искать в
Главная >> Каталог задач >> Паттерны >> Порождающие >> Абстрактная фабрика (Abstract Factory)

<< назад
распечатать обсудить >>


Абстрактная фабрика (Abstract Factory)
реализации: java, количество: 15

Aвтор: this
Дата: 16.05.2007
Просмотров: 62941
Рейтинг: 7/0,7(1)
+
реализации(исходники) +добавить

Имя

«Паттерн 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)

Если:
  1. Система не должна зависеть от того, как создаются, компонуются и представляются входящие объекты. Объекты, построенные определенным образом, просто как бы подаются на вход. источник codelab.ru codelab.ru оригинал
  2. Конкретный вариант требуемого поведения системы дают не отдельные объекты, а четко выраженное семейство связанных объектов. Объекты одного семейства должны использоваться вместе. codelab.ru источник codelab.ru оригинал
  3. Для функционирования системы необходимо одно из таким семейств взаимосвязанных объектов. Иными словами, на вход системы подается только целое семейство таких объектов, система конфигурируется одним из семейств. источник оригинал codelab.ru codelab.ru
  4. Соблюдаются некоторые условия конфиденциальности, когда не желательно предоставлять весь api библиотеки объектов, их реализацию, вместо этого – только их интерфейсы. оригинал источник codelab.ru codelab.ru

Решение

оригинал codelab.ru источник codelab.ru

Участники паттерна Абстрактная фабрика (Abstract Factory)

  1. AbstractFactory (WidgetFactory) - абстрактная фабрика.
    Объявляет общий интерфейс для операций создания абстрактных объектов – продуктов. Далее в приложении вместо абстрактных будут создаваться уже конкретные объекты какого-либо одного семейство. оригинал источник codelab.ru codelab.ru
  2. ConcreteFactory[N] (Motif WidgetFactory, PMWidgetFactory) – конкретная фабрика(класс).
    Определяет, реализует операции, создающие все объекты одного конкретного семейства. codelab.ru источник оригинал codelab.ru
  3. AbstractProduct[A-Z] (Window, ScrollBar) – абстрактный продукт(класс).
    Определяет общий интерфейс для типа объекта-продукта. A-Z в данном случае – множество таких продуктов, составляющих абстрактное семейство. оригинал codelab.ru codelab.ru источник
  4. ConcreteProduct[A-Z][N] (Motif Window, Motif ScrollBar) - конкретный продукт(класс). Определяет конкретный объект-продукт типа [A-Z], создаваемый соответствующей конкретной фабрикой [N]. источник codelab.ru оригинал codelab.ru
  5. Client – клиент.
    Другой программный модуль, фрагмент кода, дающий команды на получение конкретного семейства продуктов, пользуясь только известными интерфейсами классов AbstractFactory и AbstractProduct.

    codelab.ru оригинал codelab.ru источник

Схема использования паттерна Абстрактная фабрика (Abstract Factory)

Клиент(Client) создает единственный экземпляр ConcreteFactory, с помощью которого получает когда ему нужно все объекты соответствующего семейства. Поэтому для создания других объектов, выполняющих те же функции как-нибудь несколько иным способом, нужно лишь инстанцировать, создать другую ConcreteFactory. codelab.ru codelab.ru оригинал источник

Вопросы, касающиеся реализации паттерна Абстрактная фабрика (Abstract Factory)

  1. Абстрактная фабрика – синглтон.
    В общем случае приложению нужен лишь 1 экземпляр конкретной фабрики для каждого семейства продуктов, поэтому очень уместно применить здесь паттерн Одиночка(singleton) codelab.ru оригинал codelab.ru источник
  2. Фабричный метод для создания каждого продукта.
    Класс AbstractFactory объявляет только интерфейс для создания продуктов. Фактическое их создание - дело подклассов ConcreteProduct. Чаще всего для этой цели определяется фабричный метод для каждого продукта (см. паттерн фабричный метод). Конкретная фабрика специфицирует свои продукты путем замещения фабричного метода для каждого из них. Хотя такая реализация проста, она требует создавать новый подкласс конкретной фабрики для каждого семейства продуктов, даже если они почти ничем не отличаются.
    Если семейств продуктов может быть много, то конкретную фабрику удастся реализовать с помощью паттерна прототип. В этом случае она инициализируется экземпляром-прототипом каждого продукта в семействе и создает новый продукт путем клонирования этого прототипа. Подход на основе прототипов устраняет необходимость создавать новый класс конкретной фабрики для каждого нового семейства продуктов. codelab.ru оригинал codelab.ru источник
  3. Определение расширяемых фабрик.
    Класс AbstractFactory обычно определяет разные операции для каждого вида изготавливаемых продуктов. Виды продуктов кодируются в сигнатуре операции. Для добавления нового вида продуктов нужно изменить интерфейс класса AbstractFactory и всех зависящих от него классов.
    Более гибкий, но не такой безопасный способ - добавить параметр к операциям, создающим объекты. Данный параметр определяет вид создаваемого объекта. Это может быть идентификатор класса, целое число, строка или что-то еще, однозначно описывающее вид продукта. При таком подходе классу AbstractFactory нужна только одна операция Make с параметром, указывающим тип создаваемого объекта. (Данный прием применялся в обсуждавшихся выше абстрактных фабриках на основе прототипов и классов. Такой вариант проще использовать в динамически типизированных языках вроде Smalltalk, нежели в статически типизированных, каким является C++. Воспользоваться им в C++ можно только, если у всех объектов имеется общий абстрактный базовый класс или если объекты-продукты могут быть безопасно приведены к корректному типу клиентом, который их запросил. В разделе «Реализация» из описания паттерна фабричный метод показано, как реализовать такие параметризованные операции в C++. Но даже если приведение типов не нужно, остается принципиальная проблема: все продукты возвращаются клиенту одним и тем же абстрактным интерфейсом с уже определенным типом возвращаемого значения. Клиент не может ни различить классы продуктов, ни сделать какие-нибудь предположения о них. Если клиенту нужно выполнить операцию, зависящую отподкласса, то она будет недоступна через абстрактный интерфейс. Хотя клиент мог бы выполнить динамическое приведение типа (например, с помощью оператора dynamic_cas t в C++), это небезопасно и необязательно заканчивается успешно. Здесь мы имеем классический пример компромисса между высокой степенью гибкости и расширяемостью интерфейса) codelab.ru codelab.ru источник оригинал

Результаты

Достоинства и недостатки паттерна абстрактная фабрика. Достоинства: оригинал codelab.ru источник codelab.ru

  1. Скрываются реализации конкретных классов.
    Помогает контролировать классы объектов, создаваемых приложением. Т.е. вы остаетесь совершенно свободны от клиента в вопросе создания конкретных объектов – фабрика изолирует клиента от деталей реализации классов. Она также инкапсулирует ответственность за создание классов и сам процесс их создания. Клиенту известны лишь интерфейсы абстрактных классов, которыми через которые он только и может выполнять дальше свою бизнес логику с созданным семейством объектов. Классы отдаваемых вовне семейства объекты – известны лишь конкретной фабрике, поэтому дальше они ни в клиенте, ни в остальных частях приложения – не встречаются. оригинал codelab.ru codelab.ru источник
  2. Свободная замена семейства продуктов.
    Класс конкретной фабрики появляется в приложении только один раз: при инстанцировании. Это облегчает замену используемой приложением конкретной фабрики. Приложение может изменить конфигурацию продуктов, просто подставив новую конкретную фабрику. Поскольку абстрактная фабрика создает все семейство продуктов, то и заменяется сразу все семейство. В нашем примере пользовательского интерфейса перейти от виджетов Motif к виджетам Presentation Manager можно, просто переключившись на продукты соответствующей фабрики и заново создав интерфейс. codelab.ru оригинал codelab.ru источник
  3. Гарантия использования только одного вида продуктов
    Если продукты некоторого семейства спроектированы для совместного использования, то важно, чтобы приложение в каждый момент времени работало только с продуктами единственного семейства. Класс AbstractFactory позволяет легко соблюсти это ограничение; источник codelab.ru оригинал codelab.ru

Один из основных архитектурных недостатков – почти невозможно расширить семейство продуктов в дальнейшем. Можно сказать, что это также сложно, как и расширять интерфейс после более-менее продолжительного развития системы на его основе. Интерфейс AbstractFactory фиксирует набор продуктов, которые можно создать. Для поддержки новых продуктов необходимо расширить интерфейс фабрики, то есть изменить класс AbstractFactory и все его подклассы. оригинал источник codelab.ru codelab.ru

Пример

Применим паттерн Абстрактная фабрика к построению некоего парка автомобилей. Допустим нам нужно создавать определенное семейство автомобилей для конкретных целей. А именно нам нужны: легковые машины, грузовые и автобусы. Т.е. наша фабрика должна производить конкретные экземпляры данных видов. А дальше уже клиентская часть, используя эти возможности, будет создавать, наполнять этот парк и использовать данные автомобили по своему усмотрению в соответствии с интерфейсами их абстракных типов. codelab.ru оригинал codelab.ru источник
Класс FleetFactory может создавать разновидности автомобилей: легковые, грузовики, автобусы: FleetFactory.java codelab.ru codelab.ru оригинал источник
codelab.ru оригинал codelab.ru источник
Это фабрика. Она будет использоваться клиентской частью/программой, которая знает как создавать парк, т.е. в каких количествах наполнять его различными видами транспортных средств(например, она считывает этот план автопарка из конфигурационного файла). Этой программе на вход в качестве аргумента передается параметр типа фабрика, т.е. типа FleetFactory. оригинал codelab.ru codelab.ru источник
Далее нужны соответственно абстрактные классы продуктов (легковая машина, грузовая, автобус): Car.java, Truck.java, Bus.java codelab.ru оригинал codelab.ru источник
Допустим, нужны 2 семейства автомобилей: русские марки и американские. Соответственно, реализуем 2 абстрактные фабрики и 2 ряда продуктов-автомобилей. источник codelab.ru оригинал codelab.ru
Русская фабрика автомобилей: RusFleetFactory.java, Kamaz.java, Liaz.java, Vaz2110.java codelab.ru codelab.ru источник оригинал
Американская фабрика автомобилей: AmericanFleetFactory.java, Dodge.java, CityJet.java, GeneralMotorsTruck.java codelab.ru оригинал источник codelab.ru
И теперь – непосредственно программа-клиент. Создадим общий файл настроек, план парка, в котором будет определяться его наполнение различными видами машин, а также признак конкретной фабрики, с помощью которой он будет создаваться: источник оригинал codelab.ru codelab.ru

factory=ru
carNum=10
truckNum=2
busNum=4
источник codelab.ru codelab.ru оригинал

Следует отметить, что тот факт, что вид используемой фабрики задается в конфигурационном файле приложения, вместо того, чтобы быть жестко зашитым в его код – играет важную роль, т.к. для изменения поведения программы и используемых в ней конкретных продуктов – нужно лишь отредактировать текстовый файл. В противном случае пришлось бы перекомпилировать саму программу клиента. источник оригинал codelab.ru codelab.ru
Программа-клиент: FleetRun.java оригинал codelab.ru источник codelab.ru
Таким образом, используемый паттерн абстрактная фабрика позволяет нам в данном конкретном случае – легко и быстро менять семейство марок машин нашего парка и их количество, иными словами – прозрачно обновлять наш автопарк любыми другими машинами, не изменяя ни одной строчки в программных файлах приложения: codelab.ru codelab.ru оригинал источник

factory=us
carNum=15
truckNum=4
busNum=2
источник codelab.ru оригинал codelab.ru

Отметим, что RusFleetFactory или AmericanFleetFactory – по сути, набор фабричных методов. Это самый распространенный способ реализации паттерна абстрактная фабрика. codelab.ru codelab.ru оригинал источник
Еще заметим, что RusFleetFactory/AmericanFleetFactory - не абстрактные классы, то есть они работает и как AbstractFactory, и как ConcreteFactory. Это еще одна типичная реализация для простых применений паттерна абстрактная фабрика. Поскольку RusFleetFactory - конкретный класс, состоящий только из фабричных методов – легко получить новую фабрику FleetFactory, породив подкласс и заместив в нем только необходимые операции, т.е. не все – а лишь какие-либо необходимые! оригинал codelab.ru источник codelab.ru
Например, нужны русские легковые и грузовые машины, но вот автобусы – американские, без проблем: MixedFleetFactory.java оригинал источник codelab.ru codelab.ru
  оригинал источник codelab.ru codelab.ru

Известные применения паттерна Абстрактная фабрика (Abstract Factory)

источник codelab.ru codelab.ru оригинал


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

codelab.ru оригинал codelab.ru источник

Классы AbstractFactory часто реализуются фабричными методами, но могут быть реализованы и с помощью паттерна прототип. 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]


<< назад наверх
распечатать обсудить >>

 
каталог | задачи | паттерны | исходники | стат | форумы | карта сайта | контакты | ссылки 
© 2000-2017 CodeLAB Group
  Все права защищены
Страница сгенерирована за 0.042145 секунд
Количество запросов к БД: 14, gzip: 21.0kb/129.2kb(84%)