LazyInit - хелпер для быстрого создания методов ленивой(отложенной) инициализации.
Отложенная (ленивая) инициализация (Lazy initialization) - приём в программировании, когда некоторая ресурсоёмкая операция (создание объекта, вычисление значения) выполняется непосредственно перед тем, как будет использован её результат. Таким образом, инициализация выполняется «по требованию», а не заблаговременно.
Классический пример использования:
class DeepThought
{
protected $answer;
public function getAnswer ()
{
if ( $this->answer === null ) {
$this->answer = 42;
}
return $this->answer;
}
}
$deepThought = new DeepThought();
echo $deepThought->getAnswer(); # 42
Аналогичный пример с использованием LazyInit:
class DeepThought
{
use \iiifx\LazyInit\LazyInitTrait;
public function getAnswer ()
{
return $this->lazyInit( function () {
return 42;
} );
}
}
$deepThought = new DeepThought();
echo $deepThought->getAnswer(); # 42
Используя Composer:
$ composer require "iiifx-production/lazy-init:1.*"
LazyInitTrait содержит метод lazyInit() и свойство $lazyInitData, в котором буферизирует результаты вычислений. Предназначен для использования в объектах в динамическом контексте.
mixed lazyInit( Closure $container, string|array $dependency = null, array $params = [] )
- $container - Closure-контейнер, содержащий в себе вычисления, должен вернуть результат.
- $dependency - Строка, массив зависимостей или null - для сохранения результата вычисления. Если не указывать ключ, то он будет сгенерирован автоматически.
- $params - Дополнительные данные, которые будут переданы в Closure-контейнер при его запуске.
LazyInitStaticTrait содержит метод lazyInitStatic() и свойство $lazyInitStaticData, в котором буферизирует результаты вычислений. Предназначен для использования в статических классах в статическом контексте.
mixed lazyInitStatic( Closure $container, string|array $dependency = null, array $params = [] )
Параметры метода аналогичны.
Методы способны автоматически генерировать ключ для буферизации данных основываясь на точке вызова в коде. Это реализуется с использованием функции debug_backtrace().
Простой геттер:
class Lazy
{
use \iiifx\LazyInit\LazyInitTrait;
/**
* @return string
*/
public function getDate ()
{
return $this->lazyInit( function () {
return date( 'd.m.Y' );
}, __METHOD__ );
}
}
$lazy = new Lazy();
echo $lazy->getDate(); # '12.07.2015'
Простой геттер с автоматическим созданием ключа:
class Lazy
{
use \iiifx\LazyInit\LazyInitTrait;
/**
* @return string
*/
public function getMicrotime ()
{
return $this->lazyInit( function () {
return microtime( true );
} );
}
}
$lazy = new Lazy();
echo $lazy->getMicrotime(); # 1438928722.9734
Геттеры с зависимостью от входящих значений:
class Lazy
{
use \iiifx\LazyInit\LazyInitTrait;
/**
* @param string $string
*
* @return mixed[]
*/
public function parseString ( $string )
{
return $this->lazyInit( function () use ( $string ) { # Передаем параметр в замыкание напрямую
return explode( ':', $string );
}, [
__METHOD__,
$string,
] );
}
/**
* @param int $timastamp
*
* @return string
*/
public function formatTimastamp( $timastamp )
{
return $this->lazyInit( function ( $t ) {
return date( 'd.m.Y', $t );
}, [
__METHOD__,
$timastamp,
], [
$timastamp # Передаем параметр как свойство
] );
}
}
$lazy = new Lazy();
var_export( $lazy->parseString( 'A:B:C' ) ); # [ 0 => 'A', 1 => 'B', 2 => 'C' ]
var_export( $lazy->formatTimastamp( time() ) ); # '12.07.2015'
Использование в статических методах:
class LazyStatic
{
use \iiifx\LazyInit\LazyInitStaticTrait;
/**
* @return string
*/
public static function getDate ()
{
return self::lazyInitStatic( function () {
return date( 'd.m.Y' );
}, __METHOD__ );
}
}
echo LazyStatic::getDate(); # '12.07.2015'
Использование хелпера за пределами классов:
use iiifx\LazyInit\LazyInitHelper;
function buildString( $array )
{
return LazyInitHelper::lazyInit( function ($v) {
return implode( '.', $v );
}, 'build-string', [ $array ] );
}
echo buildString( [ 1, 5, 32 ] ); # '1.5.32'
Использование при создании одиночки(Singleton):
class Singleton
{
use \iiifx\LazyInit\LazyInitStaticTrait;
private function __construct () {}
private function __clone () {}
private function __wakeup () {}
/**
* @return static
*/
public static function getInstance ()
{
return static::lazyInitStatic( function () {
return new static();
}, __METHOD__ );
}
}
$instance = Singleton::getInstance();
Использование при создании пула одиночек(Multiton):
class Multiton
{
use \iiifx\LazyInit\LazyInitStaticTrait;
private function __clone () {}
private function __wakeup () {}
public $key;
protected function __construct ( $key )
{
$this->key = $key;
}
/**
* @param string $key
*
* @return static
*/
public static function getInstance ( $key )
{
return static::lazyInitStatic( function ( $key ) {
return new static( $key );
}, $key, [ $key ] );
}
}
echo Multiton::getInstance( 'master' )->key; # 'master'
echo Multiton::getInstance( 'slave' )->key; # 'slave'
echo Multiton::getInstance( 'master' )->key; # 'master'