Сегодня хочу продолжить тему шаблонов проектирования или, как их еще называют, паттернов.
Это вторая по счету заметка и посвящена она будет паттерну Registry, что станет, как я думаю, хорошим и логичным дополнением к первой заметке, в которой речь шла о шаблоне «Одиночка» – Singleton. Ссылку на эту заметку вы можете найти в конце.
Для тех, кто еще ничего не знает о Singleton и не хочет читать мою первую гениальную статью (сарказм, а то мало ли, что подумаете…), я в двух словах поясню, что реализует этот паттерн и для чего.
Singleton представляет собой класс со статическим интерфейсом, что делает его доступным глобально. Пожалуй, это основная идея использования «одиночки». Удобно иметь доступ к объекту класса из любой части приложения. Например, класс работы с базой данных будет очень удобен, если будет доступен глобально, но у Singleton есть еще одна особенность, которая делает его неприменимым в данном случае. Эта особенность – возможность иметь только один объект от класса реализующего шаблон Singleton. А я если наше приложение должно соединяться с двумя разными серверами БД? В таком случае одного объекта будет недостаточно, но иметь глобальный доступ к объектам все равно хочется. Вот тут нам и поможет паттерн Registry.
Пример реализации Registry
Сам по себе, Registry – этот все тот же Singleton, с тем же статическим интерфейсом. Его объект обеспечивает связь с другими объектами и делает их доступными глобально. Чтобы было понятно, о чем пойдет речь, приведу код класса, реализующего этот паттерн. Код на PHP.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | <?php class Registry { /** * Singleton registry instance * @var Singleton registry instance */ static private $_instance = null; /** * Hash table * @var array */ private $_registry = array(); /** * Get Registry instanse * * @return Singleton registry instance */ static public function getInstance() { if (is_null(self::$_instance)) { self::$_instance = new self; } return self::$_instance; } /** * Save an object by key into registry * * @param integer|string $key * @param object $object * @return void */ static public function set($key, $object) { self::getInstance()->_registry[$key] = $object; } /** * Get an object by key from registry * * @param integer|string $key * @return object */ static public function get($key) { return self::getInstance()->_registry[$key]; } /** * Private constructor * @return void */ private function __construct() { } /** * Disallow cloning * @return void */ private function __clone() { } } ?> |
Ну и небольшой пример использования. Представим, что у нас есть некоторый класс Foo, объект которого должен быть доступен глобально, но делать из этого класса одиночку мы не можем или не хотим.
1 2 3 | Registry::set('foo', new Foo()); Registry::get('foo')->bar(); |
Регистрируем объект класс Foo через статический метод Registry::set(), после чего имеем возможность получить доступ к методу Foo::bar() через статический метод реестра Registry::get().
Уверен, что если вы работали с какими-нибудь фреймворками, то не могли не встречать реализацию Registry. Так что, скорее всего, я ничего принципиально нового вам не открыл :).
Плюсы
В принципе, все плюсы я уже перечислил. Глобальный доступ – это удобно. Нет необходимости плодить множество одиночек. Теперь все они в одном месте и под строгим контролем. Ну а там, где использование паттерна Singleton, ввиду ряда причин невозможно, Registry будет выходом из ситуации.
Минусы
Минусы тоже есть, куда уж без них.
Во-первых, использование глобальных объектов может привести к тому, что проект превратиться в немасштабируемый.
Во-вторых, пусть Registry, в какой-то степени, призван заменить множество «одиночек», тем не менее, он не обеспечивает наличие только одного объекта зависимого класса. Даже если в реализации Registry мы предупредим создание двух объектов оного класса, никто не запретит разработчику действовать в обход нашего реестра.
Ну а в-третьих, мы порождаем новые зависимости. Объекты зависят от реестра и от ключей реестра. Это тоже может стать причиной плохой масштабируемости проекта.
Подходите ко всему с умом и осознанием правильности принятого решения.
Да пребудет с вами Сила!
Другие паттерны:
Автор: Мурашов Олег
Источник: http://inroot.ru/

А зачем Registrу делать еще и Singleton
Разве это не будет работать так:
class Registry
{
private static $_registry = array();
static public function set($key, $object) {
self::$_registry[$key] = $object;
}
static public function get($key) {
return self::$_registry[$key];
}
private function __construct() {}
private function __clone() {}
}
Или в этом варианте есть какие-то нюансы не видные сразу?
Зачем извращаться с созданием неудобного в использовании и требующего дополнительных ресурсов класса, который ничего не добавляет к функциональности встроенных в php суперглобальных массивов $_SESSION и $GLOBALS ?
Andrew, есть стандарты, есть паттерны, в конце концов, правила хорошего топа и принципы стиля. Это ООП и это шаблон ООП. Можно вообще не использовать ООП и писать исключительно процедурные приложения. Более того, есть целая армия приверженцев подобного подхода, впрочем, как есть и другая армия – приверженцев объектно-ориентированной разработки. И те и другие находят свои объяснения для выбранной идеологии.
Марк, ваша реализация Registry тоже часто встречается, но в том виде, в каком я предложил данный паттерн, он описывается “Бандой четырех”, а они ребята крутые и являются ориентиром в вопросах паттернов.
Честно признаться, объяснить данную реализацию я не смогу. Вообще, порой паттерны имеют избыточную реализацию, но так получается ввиду желания стандартизировать способ решения проблемы. Вдобавок, паттерны адаптируются для разных языков, что тоже иногда сказывается на конкретных реализациях в коде.
Олег, “чистое” ООП, или” чистое” структурное программирование – это бред. Надо использовать те возможности, которые предоставляет язык программирования, а уже потом задумываться о “чистоте стиля”. Если в языке есть механизмы, аналогичные Registry, то надо использовать их – как бы он не назывались, а не изобретать велосипед, снижая производительность программы.
ИМХО, именно это, а не бессмысленное размножение сущностей – хороший тон.
А паттерны – это никак не стандарт. Всего лишь относительно недавно возникшая мода, пока еще не вытесненная новыми веяниями.
Не согласен я с вами, но это лишний раз доказывает, что каждому свое. Видимо, я учился по другим книжкам.
Согласен с Марком. Как по мне, так его реализация правильнее. Чисто статический класс, от которого вообще нельзя породить ни одного объекта. А Singleton подразумевает создание экземпляра класса, хоть и одного.