Может войдёшь?
Черновики Написать статью Профиль

Использование контейнера IoC

перевод

  1. 1. Регистрация объектов
  2. 2. Получение объектов
  3. 3. Одиночки (singletons)

Контейнер IoC — неочевидная на первый взгляд возможность Laravel: его описание в документации сбивает с толку многих начинающих программистов и какое-то короткое время я сам был одним из них. Однако после копания этой темы и при поддержке замечательного сообщества Laravel на IRC-канале FreeNode #laravel эта тема полностью прояснилась. Надеюсь, я смогу пролить немного света на этот таинственный аспект Laravel в этой статье.

IoC означает «обратный контроль» («Inversion of Control»). Я не буду усложнять изложение детальным описанием этой проблемы, есть множество статей на эту тему. Вместо этого будем относиться к IoC как к «выполнение наоборот» или «возврат контроля выполнения кода в Laravel» для того, чтобы создать нужный объект.

На самом деле это всё, зачем нужен данный контейнер — создание объектов. Если не считать его применения для определения зависимостей для юнит-тестов (мы поговорим об этом позже) вы можете просто думать о нём, как о короткой форме создания сложных объектов или получения объекта-одиночки («singleton») без прямого вызова методов самого класса. Об одиночках мы поговорим чуть ниже, а пока посмотрим, как происходит регистрация объектов в контейнере IoC.
\

Регистрация объектов

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

К сожалению, наш PHPDiscoball требует установить множество конфигурационных опций перед тем, как он может быть использован. Посмотрим, как это происходит:

PHP
$db = new Discoball(Discoball::SHINY);
$db->configure_shinyness('max');
$db->spin_speed('8900rpm');

Ого, как много настроек! Ещё несколько таких вызовов и нам надоест каждый раз создавать и настраивать этот дискотечный шар («discoball»). Давайте попросим IoC делать это для нас, а сами перейдём непосредственно к коду.

Я обычно помещаю этот код в application/start.php, но вы можете делать это где угодно до тех пор, пока ваши объекты вызываются уже после того, как они зарегистрированы в контейнере IoC.

PHP
IoC::register('discoball', function () {
  
// создаём экземпляр объекта, как в примере выше:
  
$db = new Discoball(Discoball::SHINY);
  
$db->configure_shinyness('max');
  
$db->spin_speed('8900rpm');

  
// возвращаем созданный объект:
  
return $db;
});

Мы вызываем метод PHPIoC::register() для регистрации нашего объекта в контейнере. Первый параметр — строка, которая будет использована для создания объекта — я использовал слово «discoball», потому что это выглядит самым логичным. Второй параметранонимная функция («closure»), которая и создаёт сам объект.

Внутри функции вы видите уже знакомый код настройки шара. Функция возвращает новый экземпляр объекта.

Отлично! Объект зарегистрирован и это всё, что делает IoC... шучу. Давайте посмотрим, как нам теперь получить новый объект.

Получение объектов

Теперь когда у нас есть зарегистрированный объект PHPDiscoball нужно понять, как нам получить его обратно. Вот код для этого:

PHP
$db IoC::resolve('discoball');

Вот и всё! Вместо создания и настройки нового экземпляра объекта в каждом месте нашего кода мы вызываем метод PHPIoC::resolve(), передаём ему строку-идентификатор, которая была использована при регистрации и IoC вызовет анонимную функцию, привязанную к нему, которая вернёт нам новый экземпляр объекта PHPDiscoball.

Одиночки (singletons)

Получение объекта — это хорошо, но что делать, если наш дискотечный шар требует много ресурсов для поддержания каждого экземпляра и нам нужно сконструировать его только один раз? В этом случае метод PHPIoC::register не будет нам полезен, так как он создаёт новый объект при каждом запросе. Здесь в дело вступают одиночки.

Шаблон проектирования «одиночка» (Singleton pattern) означает, что вы пишите свой класс таким образом, что их экземпляр создаётся неким статическим методом, который будет возвращать один и тот же экземпляр объекта при каждом последующем вызове. Таким образом, класс создаётся только один раз на время выполнения запроса.

Вы можете легко найти больше информации по этой теме — например, в документации по PHP.

Одиночки полезны, но они требуют определённой структуры класса, чтобы работать. Контейнер IoC имеет метод PHPsignleton(), который решает эту проблему, так как с ним не требуется специальный статический метод класса для создания экземпляра объекта. Давайте зарегистрируем наш PHPDiscoball в качестве одиночки:

PHP
IoC::singleton('discoball', function () {
  
// создаём экземпляр объекта, как в примерах выше:
  
$db = new Discoball(Discoball::SHINY);
  
$db->configure_shinyness('max');
  
$db->spin_speed('8900rpm');

  
// возвращаем созданный объект:
  
return $db;
});

Как вы видите, код ничем не отличается от кода регистрации, если не считать того, что вместо метода PHPIoC::register() используется PHPIoC::singleton() с теми же параметрами.

Когда мы попытаемся получить экземпляр дискотечного шара с помощью PHPIoC::resolve() анонимная функция будет вызвана только один раз, после чего возвращённый объект будет сохранён в контейнере и все последующие вызовы PHPresolve() будут возвращаеть именно его. Например:

PHP
// здесь анонимная функция вызывается и создаёт новый экземпляр объекта:
$db IoC::resolve('discoball');

// на этот раз функция не вызывается и мы получаем тот же объект, что и строкой выше:
$another IoC::resolve('discoball');

Замечательно! Нужно отметить, что в качестве второго параметра вы можете передать методу PHPIoC::singleton() уже созданный объект и он будет возвращаться всеми последующими вызовами PHPresolve(). Например:

PHP
$db = new Discoball(Discoball::SHINY);
IoC::singleton('discoball'$db);

// получить наш дискотечный шар:
$ball IoC::resolve('discoball');

В следующий раз я расскажу, как внедрять зависимости в контейнер IoC для проведения юнит-тестов.

Как вы считаете, полезен ли этот материал? Да Нет

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.