December
2005
Паттерн Factory Method (Фабрика)
Posted in: Паттерны проектирования |
Factory Method - это паттерн создания объектов (creational pattern). Данный ?аблон проектирования предоставляет интерфейс для создания экземпляров некоторого класса. В момент создания наследники могут определить, какой класс инстанциировать. ?ными словами, Фабрика делегирует создание объектов наследникам родительского класса. Это позволяет использовать в коде программы не специфические классы, а манипулировать абстрактными объектами на более высоком уровне.
Паттерн проектирования Factory встречается очень часто. Рассмотрим неболь?ой пример на Java.
Вступление: Требования к разного рода програмным продуктам постоянно растут. Отчеты по выполнению операций приложения должны формироваться в разном виде: XML, HTML, текст и т.д. Это как раз тот случай, когда удобно использовать паттерн Factory.
Ре?ение: Класс AbstractWriter будет представлять абстракцию для записи в некоторый контекст (будь то XML-документ или текстовый файл).
public abstract class AbstractWriter {
public abstract void write(Object context);
}
У этого класса может быть любое кол-во наследников. Рассмотрим подклассы ConcreteFileWriter и ConcreteXmlWriter для записи в текстовый файл и DOM документ соответственно:
public class ConcreteFileWriter extends AbstractWriter {
public void write (Object context) {
// method body
}
}
public class ConcreteXmlWriter extends AbstractWriter {
public void write (Object context) {
// method body
}
}
Для создания нужного нам объекта можно написать следующую Фабрику:
import java.io.File;
import org.w3c.dom.Document;
public class FactoryMethod {
public AbstractWriter getWriter(Object object) {
AbstractWriter writer = null;
if (object instanceof File) {
writer = new ConcreteFileWriter();
} else if (object instanceof Document) {
writer = new ConcreteXmlWriter();
}
return writer;
}
}
В тексте программы при создании отчета нужно передать в функцию getWriter объект File или DOM документ. В результате выполнения метода мы получим нужный объект необходимого уровня абстракции.
?спользуйте паттерн Factory в следующих случаях:
- класс не имеет информации о том, какой тип объекта он должен создать;
- класс передает ответственность по созданию объектов наследникам;
- необходимо создать объект в зависимости от входящих данных.
В одной из последующих статей по проектированию мы рассмотрим паттерн Abstract Factory.
А пока что я с удовольствием выслу?аю ва?и вопросы, замечания и комментарии.
22 Comments »
RSS feed for comments on this post. TrackBack URI
Приятная и полезная статья, спасибо боль?ое.
Спасибо за краткость, теперь мне стало более понятны принципы образцов J2EE.
Спасибо, хоро?ее описание ![]()
Не могли бы вы еще также описать следующие паттерны :
Observer
Visitor
Iterator
Adapter
Заранее благодарна.
2MouseE: Вот это комментарий :). Обязательно напи?у. Скорее всего в ближай?ей статье по паттернам расскажу об Adapter’е.
Не вижу принципиальной разницы между Strategy и Factory. В одном случае создается потомок с нужным функционалом, в другом - для достижения нужного функционала создается потомок/реализация. Странно что это разные паттерны.
Работаю в области конструирования аппаратуры. Не специалист в области программирования.Подскажите как в рамках CALS-технологий создать описание электрорадиоэлементов и связей между ними на основе паттернов.
Элемент имеет: производителя и поставщика;совокупность технических характеристик; чертеж; ;связность в схеме принципиальной и т.д. Участвует в различных отно?ениях, во многих предметных областях (торговая сеть, преобразование сигнала, монтаж аппаратуры и т.д.)
Наверное не совсем удачный пример этого паттерна. Он, действительно боль?е напоминает Стратегию, а Factory Method - это производящий ?аблон и должен выдать некий продукт.
Странно. Зачем AbstractWriter делать абстрактным классом, когда можно вместо него сделать интерфейс :/ Вообще не понятный ход.
Sergey Zwezdin
Ты прав, но это детали. Просто представь что есть этот интерфейс, а абстракный клас его имплементирует и добавляет НЕК?Й(но не весь) функционал. В данном случае видем просто сокращенный вид кода.
а почему метод getWriter не static?
не вижу смысла в данном случае создавать экземпляр класса FactoryMethod…
спасибо!
to Sergey Zwezdin and Andrey Yasinetskiy: да, конечно, можно AbstractWriter сделать интерфейсом, можно метод getWriter сделать статическим. Но зачем завязываться на то, что AbstractWriter и FactoryMethod никогда не будут иметь внутреннего состояния или же что AbstractWriter не будет иметь поведения характерного для всех Writer’ов?
автору за старание боль?ое пасибо, но все же статьи не очень хоро?ие, лично мне вообще ничего не понятно.
Насколько я понял в примере (за примеры в цикле о паттернах отдельное спасибо) проиллюстрирована параметрирозованная фабрика, т. к. в фабричный метод передаётся параметр, на основе которого и создаётся конкретный подкласс AbstractWriter. Между тем, классическая фабрика, насколько я понял, ведёт себя несколько иначе: “класс спроектирован так, чтобы объекты, которые он создает, специфицировались подклассами” (Э. Гамма ‘Паттерны проектирования’). То есть должно быть несколько наследников FactoryMethod для каждого наследника AbstractWriter, а выбор остаётся за клиентом, какую из реализацию FactoryMethod выбрать. Я правильно понял?
Согла?усь с AndreyS и danik: это не совсем классический Factory Method. есть в нем что-то от стратегии. danik, очень не советую читать Гамма - труд классический, и наверно, очень хоро?, но перевод - … отвратный, мягко говоря. луч?е “ПР?МЕНЕН?Е ШАБЛОНОВ” JAVA™ СТ?ВЕН СТЕЛТ?НГ и ОЛАВ МААССЕН.
Автору отдельное спасибо, отличный сайт.
Описание паттерна - полный отстой!!!!!!
Надо гнать таких знатоков, размещающих такие поганые статьи.
Такую реализацию паттерна действительно легко перепутать со стратегией.
Реализация, как я понял, метода getWriter(Object object)в классе FactoryMethod избавляет от необходимости содавать его подклассы для создания нужных объектов. При этом, если количество возможных объектов станет на порядок боль?е, реализация фабричного метода станет не очень красивой
Описание паттерна действительно слабенькое.
Но “гнать таких знатаков” точно не стоит. Ресурс великолепный. Спасибо автору
Кратко и понятно.
To TeamLeader:
ТимЛидер говори?ь? Нормальный тимлидер в первую очередь должен уметь общаться с людьми, а не тявкать из-за поворота. Есть замечания - напи?и, поправь.
Человеку спасибо за ресурс, видно что старается.
На самом деле в примере показан вовсе не Factory Method, а так называемая Simple Factory (это даже не ?аблон проектирования, а просто ?ироко используемая техника). Правильно написал danik, что у класса FactoryMethod должны быть наследники, которые собственно и переопределяют фабричный метод. На первый взгляд может показаться, что нет никакого отличия, но отличие огромное. Прочитайте “Head First Design Patterns” или “Design Patterns For Dummies” и вам станет все понятно.
to alex
Ты неправ. Это все таки фабричный метод. Читаем у Эриха Гаммы: “параметризованные фабричные методы. Это еще один вариант паттерна, ко¬торый позволяет фабричному методу создавать разные виды продуктов. Фабричному методу передается параметр, который идентифицирует вид создаваемого объекта. Все объекты, получающиеся с помощью фабричного метода, разделяют общий интерфейс Product. В примере с документами класс Application может поддерживать разные виды документов. Вы пе¬редаете методу CreateDocument ли?ний параметр, который и определя¬ет, документ какого вида нужно создать”
Так что перед тем как высказывать свое мнение неплохо бы изучить мат часть
to TeamLeader:
тебя надо гнать, грузчиком иди работай!
Пример ваще не понятный это не патерн, по примеру палучается так:
передаём getWriter’у объект типа ConcreteXmlWriter, в результате получаем объект того же типа.