Factory Method (Фабричный метод)

Перед прочтением ознакомьтесь с введением в паттерны проектирования.
Factory Method относиться к классу порождающих паттернов. Они используются для определения и поддержания отношений между объектами. Фабричные методы избавляют проектировщика от необходимости встраивать в код зависящие от приложения классы.

Пример

Предположим мы создаем некий XML парсер, который анализирует предоставленный файл и преобразует его в DOM дерево. Каждый элемент этого дерева назовем нодой (Node). Во время разбора файла, перед нами встанет задача порождения новых нод, и мы напишем там примерно такой код:
[php]
class Xml_Node()
{
/*…*/
public function parse()
{
/*…*/
$ChildNode = new Xml_Node();
/*…*/
}
/*…*/
}
[/php]
Что в этом плохого? Приведу такой пример: мы захотим на основе XML файла строить структуру объектов, определенного класса, чтобы использовать ее в дальнейшем, и нам, в соответствии с принципом «до тебя уже все написано», захотелось использовать готовый класс XML_Node. Мы делаем своего наследника XML_Node_Processor, и хотим теперь повлиять на процесс анализа файла так, чтобы при определенном теге инстанцировался определенный класс (Для тега food — My_Food, для cow — My_Big_Orange_Cow). И при реализации как приведена выше, для этого нам придется полностью перегрузить метод parse, ради того, чтобы сделать копипаст кода из родительского класса отредактировав всего одну строку кода. Согласитесь, это глупо.

Суть паттерна


Возможная реализация на PHP
[php]
abstract class XML_Node_Abstract
{
abstract function createNode($tag);
}
class Xml_Node extends XML_Node_Abstract
{
/*…*/
public function createNode($tag)
{
return new Xml_Node();
}
/*…*/
public function parse()
{
/*…*/
$ChildNode = $this -> createNode($Tag);
/*…*/
}
}
class Xml_Node_Processor extends Xml_Node
{
public function createNode($tag)
{
switch($tag)
{
case "food":
return new My_Food();
case "cow":
return new My_Big_Orange_Cow();
}
return parent::createNode($tag);
}
}
class My_Food extends Xml_Node {};
class My_Big_Orange_Cow extends Xml_Node {};
[/php]

В заключение

  1. В реализации фабричного метода не всегда нужен абстрактный класс создателя (XML_Node_Abstract). На его месте может использоваться конкретный экземпляр. Из этого примера можно выкинуть XML_Node_Abstract и ничего не изменится
  2. Результат возвращаемый фабричным методом, должен всегда соответствовать заданному интерфейсу (в нашем случае интерфейсу класса Xml_Node)
  3. Фабричный метод может быть статической функцией, и использоваться для инстанации объектов подкласса
  4. Фабричный метод не обязательно должен возвращать объект, он так же может возвращать класс. При этом все наследники и родители так же должны возвращать класс.
Материал взят с источника

Leave a Reply