Реализация шаблона Identity Map

Тождественное отображение (Identity Map) — это просто объект, задача которого следить за всеми объектами в системе и сделать так, чтобы то, что должно быть одним объектом, вдруг не стало двумя.

На самом деле Identity Map не предотвращает эту ситуацию каким-либо активным образом. Его роль состоит в том, чтобы управлять информацией об объектах. Вот простой пример Identity Map.

class woo_domain_ObjectWatcher {

private $all = array() ;

private static $instance;

private function construct() { }

static function instance О {

if ( ! isset( self ::$instance ) ) {

self : :$instance = new woo_domain_ObjectWatcher();

}

return self : :$instance;

}

function globalKey( woo_domain_DomainObject $obj ) {

$key = get_class( $obj ).» . «.$obj->getld();

return $key;

}

static function add( woo_domain_DomainObject $obj ) {

$inst = self::instance();

$inst->all[$inst->globalKey( $obj )] = $obj;

}

static function exists! $classname, $id ) {

$inst = self::instance();

$key = «$classname.$id»;

if ( isset( $inst->all[$key] ) ) {

return $inst->all[$key];

}

return null;

}

}

На рисунке показано, как объект Identity Map может интегрироваться с другими классами, которые мы уже видели.

Главная особенность Identity Map — это, естественно, определение (идентификация) объектов. Это означает, что нужно пометить каждый объект каким-то способом. Для этого можно использовать ряд различных стратегий. Ключ таблицы базы данных, который уже используют все объекты в системе, не подходит, потому что нет гарантии, что идентификатор ID уникален для всех таблиц.

Scr13 Реализация шаблона Identity Map

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

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

Метод globalKey () обрабатывает детали этого. В этом классе предусмотрен метод add () для добавления новых объектов. Каждый объект помечается уникальным ключом в свойстве массива $all.

Методу exists () передается имя класса и идентификатор $id, а не объект. Мы не хотим создавать экземпляр объекта, чтобы узнать, существует он уже или нет! Этот метод создает ключ на основе этих данных и делает проверку чтобы узнать, индексирует ли он элемент в свойстве $all. Если объект найден, то возвращается ссылка, как и должно быть.

Есть только один класс, где я работаю с классом ObjectWatcher в его роли Identity Map. Класс Mapper обеспечивает функциональные возможности для генерации объектов, поэтому имеет смысл добавить здесь проверку.

// Mapper

private function getFromMap( $id ) {

return woo domain ObjectWatcher::exists( $this->targetClass(), $id );

}

private function addToMap( woo_domain_DomainObject $obj ) {

return woo domain ObjectWatcher::add{ $obj );

}

function find( $id ) {

$old = $this->getFromMap( $id );

if ( $old ) { return $old; }

// Работаем с db

return {object;

}

function createObj ect( {array ) {

{old = {this->getFromMap( {array['id']);

if ( {old ) { return {old; }
// Создаем объект

$this->addToMap ( $obj );

return $obj;

}

function insert( woo_domain_DomainObject $obj ) {

// Обрабатываем вставку. $obj нужно модифицировать новым идентификатором

$this->addToMap( $obj );

}

В этом классе предусмотрено два удобных метода: addToMap ( ) и getFromMap ( ). Это позволяет не беспокоиться о том, чтобы запоминать полный синтаксис статического вызова Objectwatcher. И, что еще важнее, они делают вызов к дочерним реализациям (VenueMapper и т.д.), чтобы получить имя класса, который в настоящее время ожидает создания экземпляра.

Это достигается путем вызова targetClass () , абстрактного метода, который реализуется всеми конкретными классами Mapper. Он должен вернуть имя класса, который Mapper предназначено генерировать. Вот реализация targetClass () класса SpaceMapper.

protected function targetClass() {

return «woo domain Space»;

}

И find ( ), и createObject ( ) сначала проверяют, существует ли объект, передавая идентификатор таблицы методу getFromMap ( ). Если объект найден, то он возвращается клиенту и выполнение метода заканчивается. Но если никаких версий этого объекта не существует, то создание экземпляра объекта продолжается. В createObject () этот новый объект передается методу addToMap (), чтобы предотвратить любые конфликты в будущем.

Так зачем мы проходим эту часть процесса дважды, делая вызовы к getFromMap ( ) и в find ( ), и в createObject ( ) ? Ответ на этот вопрос связан с объектами Collection. Когда они генерируют объекты, то делают это, вызывая createObject ( ). Нам нужно убедиться в том, что строка, инкапсулированная объектом Collection, не устарела, и обеспечить, чтобы самая последняя версия объекта была возвращена пользователю.

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

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

*

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