Pattern Singleton – “Одиночка”

9

С появлением некоторого количества свободного времени, я решил расширить свои знания в области паттернов проектирования. Паттерны штука полезная. Их знание и понимание очень часто облегчает жизнь, как при написании своего кода, так и при чтении чужого, конечно при условии, что он реализует тот или иной паттерн. Авось эти знания пригодятся и вам тоже, так что, милости прошу :).

Цикл статей (надеюсь, хватит сил не на одну-две) я начну с описания достаточно полезного паттерна Singleton или как его называют «Одиночка». Паттерн очень легок для понимания и в тоже время может оказаться крайне полезным, наверное, это основные причины по которым я выбрал именно его в качестве темы для первой заметки.

Пример реализации Singleton

Суть Singleton в том, чтобы класс, который его реализует, мог иметь только один экземпляр (объект) и этот экземпляр был доступен глобально, то есть доступен любым другим элементам приложения.

Сразу приведу пример такого класса (PHP 5):

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
<?php
 
class Singleton {
    /**
     * Singleton instance
     * 
     * @var object
     */
    private static $_instance;
 
    /**
     * Singleton instance
     * 
     * @return instance 
     */
    public static function getInstance() {
        if (self::$_instance === null) {
            self::$_instance = new self;   
        }
 
        return self::$_instance;
    }
 
    public function run($name) {
        echo 'Hello, ' . $name;
    }
 
    private function __construct() {        
    }
 
    private function __clone() {
    }
}
 
?>

Единственное свойство класса Singleton::$_instance хранит ссылку на экземпляр, который создается только при первом вызове статического метода Singleton::getInstance(). От повторного создания объекта уберегает условный оператор, с проверкой значения свойства и если ссылка на экземпляр уже существует, она будет возвращена.

Конструктор класса имеет модификатор доступа private, что не позволит создать объект извне. Аналогично поступаем с методом Singleton::__clone(), запрещая тем самым клонирование объекта.

Далее вся работа с классом осуществляется через уже описанный мною статический метод:

1
Singleton::getInstance()->run('World');

Хотя можно сохранить ссылку на возвращаемый объект в переменную и работать с классом избегая прямого вызова статического метода:

1
2
$obj = Singleton::getInstance();
$obj->run('World2');

Где это можно применять?

Первое, что приходит на ум в качестве возможной практики паттерна Singleton – реализация главного контроллера в приложении. Как правило, ссылка на объект главного контроллера должна быть доступна другим объектам, что в данном случае достигается за счет использования статического метода и свойства. Также главный контроллер подразумевает существования только единственного экземпляра себя.

Кстати говоря, класс Zend_Controller_Front из библиотеки популярного ZendFramework реализует этот паттерн.

Пожалуй, все :)

Другие паттерны:

Автор: Мурашов Олег
Источник: http://inroot.ru/

UPD 04.10.11:
Исправлены некоторые ошибки, упоминавшиеся в комментариях. Комментарии с упоминаниями, соответственно, были удалены ввиду потери актуальности.

Patterns

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

  1. Спасибо, очень доступно!

  2. Спасибо! Кратко-доступно-лаконично.
    Даже я понял :)
    Прочитал три статьи по паттернам :) Пока всё понятно… Ещё понятно, что много было упущено.. :)
    Пойду искать продолжение… :)
    Удачи!

  3. Еще, данный патерн используется в Code Igniter. И именно в контролере. Только он там немного не стандартный.

  4. Марк, августа 10, 2011 at 18:50 Сказал:

    А чем это удобнее вызова:
    Singleton::run('World2');
    ??

  5. Олег Мурашов, августа 10, 2011 at 23:03 Сказал:

    Если я начну отвечать на ваш вопрос, получится еще одна статья, только теперь на тему ООП и статических методов классов. Я думаю, вам лучше обратиться к какой-нибудь книге, где освещаются принципы объектно-ориентированного программирования.

  6. Марк, августа 12, 2011 at 17:43 Сказал:

    Может, вы бы могли привести более подходящий пример для которого, действительно необходимо использование данного паттерна?

  7. Олег Мурашов, августа 12, 2011 at 20:48 Сказал:

    Привел я привел – упомянул ZF, как минимум. Я думаю, дело не в примере, а в том, что вы не до конца понимаете особенности работы механизма статических методов и свойств класса, отсюда и ваш вопрос.

  8. Марк, августа 13, 2011 at 0:19 Сказал:

    К сожалению у меня нет опыта работы с ZF. В прочем, как и с паттернами программирования. И, дело даже не в том, что я, возможно, “не до конца понимаю особенности работы механизма статических методов и свойств класса”.
    Дело в том, что я не могу понять, зачем мне вообще оборачивать функцию вывода “Hello, %name%” в класс, а потом еще и запрещать создавать копии этого класса?

  9. Олег Мурашов, августа 14, 2011 at 15:38 Сказал:

    Один объект для того, чтобы изменяя его состояние, вы могли видеть эти изменения из любого места приложения. Для удобства делается статический интерфейс. Попробуйте просто написать тестовое приложение, я думаю, вы поймете смысл всего этого. Вряд ли я смогу в двух словах дать вам хорошие объяснения.

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