С появлением некоторого количества свободного времени, я решил расширить свои знания в области паттернов проектирования. Паттерны штука полезная. Их знание и понимание очень часто облегчает жизнь, как при написании своего кода, так и при чтении чужого, конечно при условии, что он реализует тот или иной паттерн. Авось эти знания пригодятся и вам тоже, так что, милости прошу :).
Цикл статей (надеюсь, хватит сил не на одну-две) я начну с описания достаточно полезного паттерна 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:
Исправлены некоторые ошибки, упоминавшиеся в комментариях. Комментарии с упоминаниями, соответственно, были удалены ввиду потери актуальности.

Спасибо, очень доступно!
Спасибо! Кратко-доступно-лаконично.
Даже я понял :)
Прочитал три статьи по паттернам :) Пока всё понятно… Ещё понятно, что много было упущено.. :)
Пойду искать продолжение… :)
Удачи!
Еще, данный патерн используется в Code Igniter. И именно в контролере. Только он там немного не стандартный.
А чем это удобнее вызова:
Singleton::run('World2');??
Если я начну отвечать на ваш вопрос, получится еще одна статья, только теперь на тему ООП и статических методов классов. Я думаю, вам лучше обратиться к какой-нибудь книге, где освещаются принципы объектно-ориентированного программирования.
Может, вы бы могли привести более подходящий пример для которого, действительно необходимо использование данного паттерна?
Привел я привел – упомянул ZF, как минимум. Я думаю, дело не в примере, а в том, что вы не до конца понимаете особенности работы механизма статических методов и свойств класса, отсюда и ваш вопрос.
К сожалению у меня нет опыта работы с ZF. В прочем, как и с паттернами программирования. И, дело даже не в том, что я, возможно, “не до конца понимаю особенности работы механизма статических методов и свойств класса”.
Дело в том, что я не могу понять, зачем мне вообще оборачивать функцию вывода “Hello, %name%” в класс, а потом еще и запрещать создавать копии этого класса?
Один объект для того, чтобы изменяя его состояние, вы могли видеть эти изменения из любого места приложения. Для удобства делается статический интерфейс. Попробуйте просто написать тестовое приложение, я думаю, вы поймете смысл всего этого. Вряд ли я смогу в двух словах дать вам хорошие объяснения.