Pattern Registry – “Реестр”

7

Сегодня хочу продолжить тему шаблонов проектирования или, как их еще называют, паттернов.

Это вторая по счету заметка и посвящена она будет паттерну 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/

Patterns

Комментарии (7 комментариев)

  1. Марк, августа 20, 2011 at 14:30 Сказал:

    А зачем 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() {}
    }

    Или в этом варианте есть какие-то нюансы не видные сразу?

  2. Andrew, августа 21, 2011 at 23:32 Сказал:

    Зачем извращаться с созданием неудобного в использовании и требующего дополнительных ресурсов класса, который ничего не добавляет к функциональности встроенных в php суперглобальных массивов $_SESSION и $GLOBALS ?

  3. Олег Мурашов, августа 22, 2011 at 1:00 Сказал:

    Andrew, есть стандарты, есть паттерны, в конце концов, правила хорошего топа и принципы стиля. Это ООП и это шаблон ООП. Можно вообще не использовать ООП и писать исключительно процедурные приложения. Более того, есть целая армия приверженцев подобного подхода, впрочем, как есть и другая армия – приверженцев объектно-ориентированной разработки. И те и другие находят свои объяснения для выбранной идеологии.

  4. Олег Мурашов, августа 22, 2011 at 1:18 Сказал:

    Марк, ваша реализация Registry тоже часто встречается, но в том виде, в каком я предложил данный паттерн, он описывается “Бандой четырех”, а они ребята крутые и являются ориентиром в вопросах паттернов.

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

  5. Andrew, августа 24, 2011 at 8:29 Сказал:

    Олег, “чистое” ООП, или” чистое” структурное программирование – это бред. Надо использовать те возможности, которые предоставляет язык программирования, а уже потом задумываться о “чистоте стиля”. Если в языке есть механизмы, аналогичные Registry, то надо использовать их – как бы он не назывались, а не изобретать велосипед, снижая производительность программы.

    ИМХО, именно это, а не бессмысленное размножение сущностей – хороший тон.

    А паттерны – это никак не стандарт. Всего лишь относительно недавно возникшая мода, пока еще не вытесненная новыми веяниями.

  6. Олег Мурашов, августа 27, 2011 at 12:11 Сказал:

    Не согласен я с вами, но это лишний раз доказывает, что каждому свое. Видимо, я учился по другим книжкам.

  7. Кирилл, декабря 24, 2011 at 13:15 Сказал:

    Согласен с Марком. Как по мне, так его реализация правильнее. Чисто статический класс, от которого вообще нельзя породить ни одного объекта. А Singleton подразумевает создание экземпляра класса, хоть и одного.

Оставить комментарий