Простая фабрика (Simple Factory) — шаблон проектирования

16 января 2020
Шаблон проектирования упрощает создание объектов, инкапсулируя логику создания в класс-фабрику и тем самым скрывает её от клиентского кода.

Пример задачи: создание объектов ценных бумаг (акции, облигации, опционы).

Ниже приведён пример использования шаблона на языке PHP. Скачать исходники (ZIP, 2 Кб)

Имеется класс фондовой биржи StockExchange и есть классы ценных бумаг, которыми торгует данная биржа: акции, облигации и опционы. Необходимо реализовать вывод графика стоимости ценной бумаги.


stock_exchange.php

Cодержит классы:
  • StockExchange — класс фондовой биржи. Класс является фабрикой, которая с помощью метода createPaper создаёт и возвращает объекты ценных бумаг;
  • Share — класс ценной бумаги «Акция». Содержит метод writeGraph, который отрисовывает график акции;
  • Bond — класс ценной бумаги «Облигация». Содержит метод writeGraph, который отрисовывает график облигации;
  • TradingOption — класс ценной бумаги «Опцион». Содержит метод writeGraph, который отрисовывает график опциона.
<?php

/**
 * Класс Фондовой биржи
 */
class StockExchange
{
    /**
     * Создаёт объект ценной бумаги
     * @param string $type - тип бумаги. Доступны следующие значения:
     *                       'share' - акция
     *                       'bond' - облигация
     *                       'trading_option' - опцион
     * @param string $ticker - тикер бумаги
     * @return object|bool - вернёт объект бумаги или 'false' в случае ошибки
     */
    public static function createPaper($type, $ticker)
    {
        switch ($type)
        {
            case 'share':
            {
                return new Share($ticker);
                break;
            }
            case 'bond':
            {
                return new Bond($ticker);
                break;
            }
            case 'trading_option':
            {
                return new TradingOption($ticker);
                break;
            }
            default:
            {
                throw new Exception('Указанный тип бумаг ('.$type.') не поддерживается');
                break;
            }
        }

        return false;
    }
}

/**
 * Класс ценной бумаги "Акция"
 */
class Share
{
    /**
     * Тикер бумаги
     * @var string
     */
    private $ticker;

    /**
     * Конструктор объекта
     * @param string $ticker - тикер бумаги
     */
    public function __construct($ticker)
    {
        $this->ticker = $ticker;
    }

    /**
     * Выводит график акции
     * @return void
     */
    public function writeGraph()
    {
        echo 'График акции '.$ticker.'<br>';
    }
}

/**
 * Класс ценной бумаги "Облигация"
 */
class Bond
{
    /**
     * Тикер бумаги
     * @var string
     */
    private $ticker;

    /**
     * Конструктор объекта
     * @param string $ticker - тикер бумаги
     */
    public function __construct($ticker)
    {
        $this->ticker = $ticker;
    }

    /**
     * Выводит график акции
     * @return void
     */
    public function writeGraph()
    {
        echo 'График облигации '.$ticker.'<br>';
    }
}

/**
 * Класс ценной бумаги "Опцион"
 */
class TradingOption
{
    /**
     * Тикер бумаги
     * @var string
     */
    private $ticker;

    /**
     * Конструктор объекта
     * @param string $ticker - тикер бумаги
     */
    public function __construct($ticker)
    {
        $this->ticker = $ticker;
    }

    /**
     * Выводит график акции
     * @return void
     */
    public function writeGraph()
    {
        echo 'График опциона '.$ticker.'<br>';
    }
}

?>

test_1.php

Тестовый клиентский код, где с помощью статического метода StockExchange::createPaper создаются три ценные бумаги (акция, облигация и опцион), а затем методом writeGraph выполняется отрисовка их графиков. 

С помощью класса-фабрики мы убрали прямое создание объектов методом new и передали логику создания внутрь фабрики. 
<?php

//Подключение класса Фондовой биржи
require_once(__DIR__.'/stock_exchange.php');

//Создаём ценные бумаги
$share = StockExchange::createPaper('share', 'MCX:SBER');
$bond = StockExchange::createPaper('bond', 'SU26218RMFS6');
$tradingOption = StockExchange::createPaper('trading_option', 'RI125000BE9');

//Выводим графики
$share->writeGraph();
$bond->writeGraph();
$tradingOption->writeGraph();

?>

Результат работы тестового скрипта
График акции
График облигации
График опциона

В случае с фабрикой клиентской код зависит напрямую только от класса фондовой биржи StockExchange. А если реализовать задачу без участия фабрики, то получившийся код будет более зависимым, потому что вместо одного класса, он напрямую станет зависеть от трёх классов: Share (акция), Bond (облигация) и TradingOption (опцион).
<?php

//Подключение класса Фондовой биржи
require_once(__DIR__.'/stock_exchange.php');

//Создаём ценные бумаги
$share = new Share('MCX:SBER');
$bond = new Bond('SU26218RMFS6');
$tradingOption = new TradingOption('RI125000BE9');

//Выводим графики
$share->writeGraph();
$bond->writeGraph();
$tradingOption->writeGraph();

?>