Шаблоны проектирования: Factory Method

Коротко говоря Factory Method (Фабричный метод) — предоставляет подклассам некоторого класса фабрики (создателя) возможность создавать свойственные им конкретные продукты.

Когда применять? Если класс фабрика начинает обрастать логикой по созданию разного типа объектов (продуктов) и методы начинают содержать дублированные ветвления.

Пример: пусть у нас есть класс фабрики статей задача которого предоставлять по запросу коллекции статей заданного типа.

<?php

class ArticlesFactory
{
    function getArticles($type)
    {
        switch($type)
        {
            case 'game':
                $articles = new GameArticles(); break;
            case 'video':
                $articles = new VideoArticles(); break;
            default:
                throw new Exception('$type not defined');
        }

        return $articles;
    }

    function info($type)
    {
        switch($type)
        {
            case 'game':
                $info = 'Статьи о играх'; break;
            case 'video':
                $info = 'Статьи о видео'; break;
            default:
                throw new Exception('$type not defined');
        }

        return $info;
    }
}

interface Articles
{
    function get($articleId);
}

class GameArticles implements Articles
{
    function get($articleId)
    {
        return 'Статья об играх под #id '.$articleId;
    }
}

class VideoArticles implements Articles
{
    function get($articleId)
    {
        return 'Статья о видео под #id '.$articleId;
    }
}

$articlesFactory = new ArticlesFactory();
echo $articlesFactory->info('video');

$articles = $articlesFactory->getArticles('video');
echo '<p>'.$articles->get(rand(1,100)).'</p>';

?>

после выполнения получим вывод примерно следующего содержания

Статьи о видео
Статья о видео под #id 16

В коде намерено опущена проверка на ошибки для простоты примера. Главные участники здесь: ArticlesFactory — фабрика статей (в терминологии шаблона «создатель») и Articles — наборы статей (продукт).

На лицо несколько проблем:

  • Дублирование кода (Добавление нового метода в фабрику (например подсчета количества статей заданного типа) приведет к очередному дубликату конструкции switch
  • Тесная связь (Добавление нового типа статей приведет к правке всех методов фабрики)

Шаблон Factory Method предлагает для решения этих проблем создать специфичные фабрики для каждого из продуктов, т.е. фактически свеcти реализацию к полиморфизму.

<?php

interface ArticlesFactory
{
    function getArticles();
    function info();
}

class GameArticlesFactory implements ArticlesFactory
{
    function getArticles()
    {
        return new GameArticles();
    }

    function info()
    {
        return 'Статьи о играх';
    }
}

class VideoArticlesFactory implements ArticlesFactory
{
    function getArticles()
    {
        return new VideoArticles();
    }

    function info()
    {
        return 'Статьи о видео';
    }
}

interface Articles
{
    function get($articleId);
}

class GameArticles implements Articles
{
    function get($articleId)
    {
        return 'Статья об играх под #id '.$articleId;
    }
}

class VideoArticles implements Articles
{
    function get($articleId)
    {
        return 'Статья о видео под #id '.$articleId;
    }
}

$videoArticlesFactory = new GameArticlesFactory();
echo $videoArticlesFactory->info();
$articles = $videoArticlesFactory->getArticles();
echo '<p>'.$articles->get(rand(1,100)).'</p>';

?>

Перечислим основные плюсы такого подхода:

  • Клиентский код по созданию объектов стал более универсален и не привязан к конкретному продукту (типу статей), а оперирует общим интерфейсом ArticlesFactory
  • Однозначная связь между параллельными иерархиям классов

Не обошлось и без минусов:

  • Необходимо создавать новую фабрику под каждый новый тип статей


Теги: ,

Оставить комментарий

Premium Wordpress Themes