Pattern Singleton – «Одиночка»

4 марта 2012

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

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

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

Предположим, что в вашем приложении есть объект, в котором хранятся данные конфигурации приложения. Разумеется, данные конфигурации должны быть доступны разным частям приложения на всех уровнях.

Согласно идеологии ООП, для получения доступа к переменной, например, внутри метода объекта, ее необходимо передать в качестве параметра этого метода или конструктора. Необходимо стараться следовать этому принципу всегда, когда это возможно. Но, в описанной ситуации, трудно представить, через какое количество объектов придется протащить экземпляр класса работы с конфигом.
В PHP есть два способа поместить данные в глобальную область видимости, тем самым, сделать их доступными из любого места программы. Первый – использование суперглобального ассоциативного массива $GLOBALS, содержащего все переменные, объявленные в глобальной области видимости. Второй – использование ключевого слова global, вводящего переменную в текущую область видимости. Какой способ хуже, я затрудняюсь даже предположить. Как бы там ни было, в других языках программирование подобные средства отсутствуют и паттерн Singleton становится единственным способом введения объекта в глобальное пространство.

Класс, реализующий паттерн Singleton становится доступным глобально за счет статического интерфейса. Также к числу его особенностей необходимо отнести блокирование конструктора класса и магических методов __clone() и __wakeup(), описывая их с модификатором доступа private. Это делается для того, чтобы не допустить создание более одного объекта от класса.

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
<?php
 
class Singleton {
    /**
     * Singleton instance
     * 
     * @var Singleton
     */
    protected static $_instance;
 
    /**
     * Return singleton instance
     * 
     * @return Singleton 
     */
    public static function getInstance() {
        if (self::$_instance === null) {
            self::$_instance = new self;   
        }
 
        return self::$_instance;
    }
 
    public function Foo() {
        $this->newPropetry = 'string';
    }
 
    public static function staticFoo() {
        return self::getInstance();
    }
 
    private function __wakeup() {
    }
 
    private function __construct() {        
    }
 
    private function __clone() {
    }
}
 
Singleton::getInstance()->Foo();
 
var_dump(Singleton::staticFoo());
 
?>

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

Свойство Singleton::$_instance объявлено с модификатором protected, дабы класс можно было наследовать. Нередко паттерн реализуют с сокрытием этого свойства за модификатором private.

Реализацию шаблона Одиночка можно посмотреть, например, в классе CI_Controller из фреймворка CodeIgniter или Zend_Controller_Front из ZendFramework.

Тэги:
Категория: UML и Design Patterns

Мурашов Олег

Программист и фрилансер из Санкт-Петербурга. Помимо веб-программирования, занимаюсь разработкой мобильных приложений для платформы Android. Играю на бас гитаре. Занимаюсь спортом.

2 Responses to Pattern Singleton – «Одиночка»

  1. Anon+ says:

    Спасибо за пример.
    Строка №46 var_dimp(), Вы имели в виду var_dump() ?

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

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

*