Реализация шаблона Lazy Load

Как вы, наверное, знаете, применить шаблон Lazy Load — значит отложить получение свойства до тех пор, пока его действительно не запросит клиент.

Как мы видели, самый простой способ для этого — сделать задержку явной в содержащем объекте. Вот как это можно сделать в объекте Space.

// Space

function getEvents() {

if ( is_null($this->events) ) {

$this->events =

self ::getFinder(‘woo domain_Event’)->findBySpaceId( $this->getld() );

}

return $this->events;

}

Этот метод проверяет, установлено свойство $events или нет. Если оно не установлено. то метод получает средство поиска (т.е. Mapper) и использует его собственное свойство $id для получения объекта EventCollection, с которым он связан. Очевидно, чтобы этот метод избавил нас от ненужных запросов к базе данных, нам также нужно скорректировать код SpaceMapper, чтобы он автоматически не выполнял предварительную загрузку объекта EventCollection.

Этот подход будет отлично работать, хотя он немного беспорядочный. Не лучше ли убрать этот беспорядок?

В результате мы возвращаемся к реализации Iterator, которая создает объект Collection. Мы уже скрываем один секрет за этим интерфейсом (то, что необработанные данные могли еще не использоваться для создания экземпляра объекта приложения в то время, когда клиент обращается к нему). Вероятно, мы можем скрыть еще больше.

Идея заключается в том, чтобы создать объект EventCollection который откладывает обращение к базе данных до тех пор, пока не будет сделан запрос на это. Это означает, что клиентскому объекту (такому как Space, например) никогда не нужно знать, что он содержит пустой объект Collection в своем первом экземпляре. Что касается клиента, то он содержит абсолютно нормальный объект EventCol lection. Вот объект DeferredEventCollection.

class woo_mapper_DeferredEventCollection

extends woo_mapper_EventCollection {

private $stmt;

private $valueArray;

private $run=false;

function_construct( woo_mapper_Mapper $mapper, PDOStatement

$stmt_handle,

array $valueArray ) {

parent::_construct( null, $mapper );

$this->stmt = $stmt_handle;

$this->valueArray = $valueArray;

}

function notifyAccess() {
if ( ! $this->run ) {

$this->stmt->execute( $this->valueArray );

$this->raw = $this->stmt->fetchAll();

$this->total = count( $this->raw );

}

$this->run=true;

}

}

Как видите, этот класс расширяет стандартный EventCollection. Его конструктор требует объекты EventMapper и PDOStatement и массив сроков, который должен соответствовать подготовленному оператору. В первом случае класс ничего не делает, а только сохраняет свои свойства и ждет. Никаких запросов к базе данных не делается.

Если вы помните, в базовом классе Collection определяется пустой метод notifyAccess ( ), о котором я упоминал в записи Шаблон Data Mapper. Он вызывается из любого метода, вызов которого был выполнен извне.

В классе DeferredEvent Collection этот метод замещается. Теперь, если кто-то попытается обратиться к Collection, этот класс будет знать, что пришло время перестать притворяться и получить какие-то реальные данные. Он делает это, вызывая метод PDOStatement : : execute ( ). Вместе с методом PDOStatement :: fetch ( ) это дает массив полей, подходящих для передачи методу Mapper::createObject ( ). Вот метод в EventMapper, который создает экземпляр DeferredEventCollection.

function findBySpaceld( $s_id ) {

return new woo_mapper_DeferredEventCollection(

$this, $this->selectBySpaceStmt, array( $s id ) );

}

«Ленивая» загрузка — это привычка, которую стоит приобрести, добавляете ли вы явно логику отложенной загрузки к доменным классам или нет.

Помимо безопасности типа, особое преимущество использования для свойств коллекции, а не массива, — это возможность, позволяющая изменить процесс «ленивой» загрузки, если вам это понадобится.

Советую прочитать также

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Перед отправкой формы: