30
December

Паттерн 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.
А пока что я с удовольствием выслушаю ваши вопросы, замечания и комментарии.

13 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 выбрать. Я правильно понял?

Leave a comment

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