+7 495 008 8452 пн.-пт. 10:00 – 17:00
Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.


Что такое фабрики в PHP

Нет, тут не будет подробного объяснения что это за паттерны и с чем их едят, и описаний  десятков ситуаций, которые, быть может, вообще вам никогда не пригодятся. Я вообще противник всего искусственного и выступаю за обучение на практике. Просто в помощь почаще надо призывать элементарную логику, и все получится.

Простая задача, с которой я столкнулся. Есть набор однотипных классов с одинаковыми методами. Причем подразумевается постоянное расширение этого множества. Так как я обещал практику, пусть это будет игровой бот в игре, который умеет:
  • рождаться
  • нападать
  • умирать
Почему мы не можем все затолкать в один класс? Ну как минимум, мы даем возможность расширения игры ботами, а также подразумеваем, что у каждого бота своя уникальная природа поведения. Всего три метода, но они всегда разные.

Так как все три метода должны быть строго обязательны у каждого бота, я обязал их быть через интерфейс:
interface iBot
{
   public function born();
   public function attack();
   public function destruct();
}


Зачем я допустил такую заумность? Просто чтобы расширяющему ботов разработчику PHP сразу выдал исключение, если он запустит своего бота в систему. Это убережет от ошибок, не видных на первый взгляд.

Программируем бота:
class Test implements iBot
{
   public function born()
   {
   }

   public function attack()
   {
   }

   public function destruct()
   {
   }
}


Ну а теперь нам осталось сделать общий некий класс, чтобы делать вот так:
$a = new Bot('Test');//передаем имя бота, совпадающее с именем его класса
$a->born();
$a->attack();
$a->destruct();


В начале я упомянул логику. Что подсказывает логика? Логика подсказывает сделать вот так:
class Bot
{
   public function __construct($id)
   {
      return new $id;
   }
}


То есть мы хотим создать новый класс внутри класса и вернуть его, чтобы дальше (в Игре) нам не задумываться о том, каким ботом мы орудуем (и  их может быть много). И радостно ждем результата. Неа, результата не будет, потому что ну вот так вот. Нельзя так делать.

Что подсказывает дальше логика? Избавиться от внешнего new, и переделать  класс Bot примерно вот так:
class Bot
{
   public function create($id)
   {
      return new $id;
   }
}


Тогда вызов у нас стал полностью "абстрактен":
$a = Bot::create('test');
$a->born();
$a->attack();
$a->destruct();


И тут появляется вопрос, почему сразу нельзя сделать new Test? Тут данная логика опущена, но:
  • бота может не существовать, или он уже выведен из игры, система должна адекватно отреагировать на уровне create
  • бот может быть не доступен на данной локации, аналогично должна игра отреагировать
  • в конце концов, мы можем запустить создание в цикле, чтобы заполнить ботами локацию, и нам до фени какие боты будут
После этого я узнал, что данный подход называется "фабрика" или "factory". Мне это почему-то не пригождалось целых 10 лет, и я рад, что я не забивал голову этой ерундой. Осталась чиста логика :)

PS: А собеседующих при приеме на работу разными умными паттернами я вам предлагаю послать нафик и дать почитать этот пример из жизни.

Назад в раздел

Подписаться на новые материалы раздела:














CAPTCHA