30
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



cDima
January 25, 2006 #

Приятная и полезная статья, спасибо боль?ое.

Larsen
March 13, 2006 #

Спасибо за краткость, теперь мне стало более понятны принципы образцов J2EE.

MouseE
March 17, 2006 #

Спасибо, хоро?ее описание :)
Не могли бы вы еще также описать следующие паттерны :
Observer
Visitor
Iterator
Adapter

Заранее благодарна.

March 17, 2006 #

2MouseE: Вот это комментарий :). Обязательно напи?у. Скорее всего в ближай?ей статье по паттернам расскажу об Adapter’е.

Javaстик
September 18, 2006 #

Не вижу принципиальной разницы между Strategy и Factory. В одном случае создается потомок с нужным функционалом, в другом - для достижения нужного функционала создается потомок/реализация. Странно что это разные паттерны.

Валерий
September 26, 2006 #

Работаю в области конструирования аппаратуры. Не специалист в области программирования.Подскажите как в рамках CALS-технологий создать описание электрорадиоэлементов и связей между ними на основе паттернов.
Элемент имеет: производителя и поставщика;совокупность технических характеристик; чертеж; ;связность в схеме принципиальной и т.д. Участвует в различных отно?ениях, во многих предметных областях (торговая сеть, преобразование сигнала, монтаж аппаратуры и т.д.)

AndreyS
December 6, 2007 #

Наверное не совсем удачный пример этого паттерна. Он, действительно боль?е напоминает Стратегию, а Factory Method - это производящий ?аблон и должен выдать некий продукт.

January 18, 2008 #

Странно. Зачем AbstractWriter делать абстрактным классом, когда можно вместо него сделать интерфейс :/ Вообще не понятный ход.

ash
February 7, 2008 #

Sergey Zwezdin
Ты прав, но это детали. Просто представь что есть этот интерфейс, а абстракный клас его имплементирует и добавляет НЕК?Й(но не весь) функционал. В данном случае видем просто сокращенный вид кода.

March 20, 2008 #

а почему метод getWriter не static?
не вижу смысла в данном случае создавать экземпляр класса FactoryMethod…

спасибо!

March 22, 2008 #

to Sergey Zwezdin and Andrey Yasinetskiy: да, конечно, можно AbstractWriter сделать интерфейсом, можно метод getWriter сделать статическим. Но зачем завязываться на то, что AbstractWriter и FactoryMethod никогда не будут иметь внутреннего состояния или же что AbstractWriter не будет иметь поведения характерного для всех Writer’ов?

andrew
June 1, 2008 #

автору за старание боль?ое пасибо, но все же статьи не очень хоро?ие, лично мне вообще ничего не понятно.

danik
June 27, 2008 #

Насколько я понял в примере (за примеры в цикле о паттернах отдельное спасибо) проиллюстрирована параметрирозованная фабрика, т. к. в фабричный метод передаётся параметр, на основе которого и создаётся конкретный подкласс AbstractWriter. Между тем, классическая фабрика, насколько я понял, ведёт себя несколько иначе: “класс спроектирован так, чтобы объекты, которые он создает, специфицировались подклассами” (Э. Гамма ‘Паттерны проектирования’). То есть должно быть несколько наследников FactoryMethod для каждого наследника AbstractWriter, а выбор остаётся за клиентом, какую из реализацию FactoryMethod выбрать. Я правильно понял?

Pavel
August 3, 2008 #

Согла?усь с AndreyS и danik: это не совсем классический Factory Method. есть в нем что-то от стратегии. danik, очень не советую читать Гамма - труд классический, и наверно, очень хоро?, но перевод - … отвратный, мягко говоря. луч?е “ПР?МЕНЕН?Е ШАБЛОНОВ” JAVA™ СТ?ВЕН СТЕЛТ?НГ и ОЛАВ МААССЕН.
Автору отдельное спасибо, отличный сайт.

TeamLeader
October 4, 2008 #

Описание паттерна - полный отстой!!!!!!
Надо гнать таких знатоков, размещающих такие поганые статьи.

NoName
March 13, 2009 #

Такую реализацию паттерна действительно легко перепутать со стратегией.
Реализация, как я понял, метода getWriter(Object object)в классе FactoryMethod избавляет от необходимости содавать его подклассы для создания нужных объектов. При этом, если количество возможных объектов станет на порядок боль?е, реализация фабричного метода станет не очень красивой

Описание паттерна действительно слабенькое.

Но “гнать таких знатаков” точно не стоит. Ресурс великолепный. Спасибо автору

SMRS
March 17, 2009 #

Кратко и понятно.

leafox
August 10, 2009 #

To TeamLeader:

ТимЛидер говори?ь? Нормальный тимлидер в первую очередь должен уметь общаться с людьми, а не тявкать из-за поворота. Есть замечания - напи?и, поправь.

Человеку спасибо за ресурс, видно что старается.

alex
September 22, 2009 #

На самом деле в примере показан вовсе не Factory Method, а так называемая Simple Factory (это даже не ?аблон проектирования, а просто ?ироко используемая техника). Правильно написал danik, что у класса FactoryMethod должны быть наследники, которые собственно и переопределяют фабричный метод. На первый взгляд может показаться, что нет никакого отличия, но отличие огромное. Прочитайте “Head First Design Patterns” или “Design Patterns For Dummies” и вам станет все понятно.

Igor
October 22, 2009 #

to alex
Ты неправ. Это все таки фабричный метод. Читаем у Эриха Гаммы: “параметризованные фабричные методы. Это еще один вариант паттерна, ко¬торый позволяет фабричному методу создавать разные виды продуктов. Фабричному методу передается параметр, который идентифицирует вид создаваемого объекта. Все объекты, получающиеся с помощью фабричного метода, разделяют общий интерфейс Product. В примере с документами класс Application может поддерживать разные виды документов. Вы пе¬редаете методу CreateDocument ли?ний параметр, который и определя¬ет, документ какого вида нужно создать”
Так что перед тем как высказывать свое мнение неплохо бы изучить мат часть

qw
April 30, 2010 #

to TeamLeader:
тебя надо гнать, грузчиком иди работай!

xxx
July 8, 2010 #

Пример ваще не понятный это не патерн, по примеру палучается так:
передаём getWriter’у объект типа ConcreteXmlWriter, в результате получаем объект того же типа.

Leave a comment

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong> <pre>