@romicohen
Системный Архитектор

В чем преимущество «фабричного метода» перед простым созданием объектов?

В Вики приводится такой пример:

<?php
abstract class Animal
{
    public static function initial($animal)
    {
        return new $animal();
    }
    abstract public function voice();
}

class Lion extends Animal
{
    public function voice()
    {
        echo 'Rrrrrrrr i\'m the lion <br />' . PHP_EOL;
    }
}

class Cat extends Animal
{
    public function voice()
    {
        echo 'Meow, meow i\'m the kitty <br />' . PHP_EOL;
    }
}

$animal1 = Animal::initial('Lion');
$animal2 = Animal::initial('Cat');

$animal1->voice();
$animal2->voice();


но я не понимаю, чем именно это лучше, нежели простое:

(new Cat())->voice();

в чем смысл?

Спасибо.
  • Вопрос задан
  • 376 просмотров
Решения вопроса 3
usdglander
@usdglander Куратор тега PHP
Yipee-ki-yay
Просто пример дурацкий. Представьте что вам нужно в зависимости от времени суток создавать разных животных. Ночью львов, днём котят. Причём не в одном месте приложения. Тогда метод initial будет включать в себя проверку на время суток и в зависимости от этого отдавать нужное животное. Причём так будет автоматически происходить везде где вызывается Animal::initial().
Ответ написан
myks92
@myks92 Куратор тега PHP
Нашёл решение — пометь вопрос ответом!
Фабричный метод — это порождающий паттерн проектирования, который определяет общий интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов.

В PHP, в отличии от других некоторых языков конструктор один. Из-за чего объект нельзя создать несколькими способами, с другими бизнес правилами. Поэтому принято конструктор делать приватным, а объект создавать через фабричные методы вроде create(), requestJoinByEmail(), joinByNetwork() и другие.

Возьмём всем известных User-ов, которые могут появиться в нашей системе по-разному:

1. Создание пользователя Администратором через метод create().
2. Регистрацией пользователя по Email через метод requestJoinByEmail().
3. Регистрацией пользователя через социальную сеть через метод joinByNetwork().

Таким образом наш объект становится более гибким и содержит в себе разные бизнес требования к состоянию в зависимости от способа его создания.

Чтобы хорошо понять суть рекомендую прочитать полезный ресурс — Refactoring Guru - Фабричный метод.
Ответ написан
@xfg
Проблема, которую решает фабричный метод - это возможность отложить создание объекта на попозже. Скажем, у вас имеется некий алгоритм, в котором на одном из шагов требуется создание объекта. Вы знаете, что у вас может быть несколько различных реализаций такого объекта. Тогда вы можете создать фабричный метод и использовать его в своем алгоритме для создания объекта. Это позволяет вам переложить ответственность по созданию объекта на подклассы и таким образом написать общий алгоритм не привязываясь к конкретной реализации объекта.

Советую для понимания посмотреть пример в англоязычной википедии и там же реализацию на Java. Суть в том, что у вас есть игра лабиринт. И есть два режима игры, обычный - когда игрок может перемещаться из комнаты только в смежную комнату и магический режим - когда игрок может перемещаться в любую комнату. Алгоритм самой игры для обоих режимов один и тот же, а вот бизнес-правила перемещения игрока по комнатам - разные. Вы реализуете эти бизнес-правила в OrdinaryRoom и MagicRoom, а в самом алгоритме игры вместо того, чтобы создавать какой-то из этих объектов - вызываете просто абстрактный метод makeRoom(). А затем создаете два подкласса, которые будут реализовывать метод makeRoom и возвращать нужный тип комнаты. Таким образом вы получаете два различных режима игры написав один алгоритм.

Вообще смысл данного шаблона довольно сложно понять. В интернете его почти всегда объясняют неверно. Прямо как пример на C#. Это совсем не то, о чем писали в книге банды четырех. Пример соответствующий тому о чем рассказывается в книге реализован в примере на Java. Нужно приложить усилия и постараться вникнуть в идею. Можно перед этим изучить Template method, его проще понять, там похожая идея, только там вы перекладываете часть поведения на подклассы, а здесь перекладываете создание объекта на подклассы. Factory method практически всегда используется в связке с Template method если мы говорим о классической реализации шаблона из книги банды четырех.

Вообще шаблон не настолько распространенный насколько может показаться. Мне с 2002 года в моей практике не пригодился ни разу.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы