Цель шаблона:
- Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.
- Существенно то, что можно пользоваться именно экземпляром класса, т.к. при этом во многих случаях становится доступной более широкая функциональность.
Применение:
- Когда нам нужен только один экземпляр класса, легко доступный всем клиентам; т.е. чтобы люди не плодили объектов.
- Единственный экземпляр должен расширяться путем порождения подклассов, и клиентам нужно иметь возможность работать с расширенным экземпляром без модификации своего кода.
Т.е. общая идея этого шаблона — мы сооружаем класс, от которого можно воспроизвести только один объект. Фактически все свойства класса объявляются приватными (private).
Рассмотрим простой шаблон singleton:
class DbConn{ const DB_NAME = 'mydb.db'; private $_db; static private $_instance = null; private function __construct (){ $this->db = new SQLitease (self::DB_NAME);} //придет экзепляр класса private function __clone(){} static function getInstance(){ if(self::$_instance == null) (self::$_instance = new DbConn(); } return self::$_instance;}}
У нас есть класс DnConn. В нем происходит соединение с базой данных и удерживается. Есть private свойство. Есть статическое private свойство $_instance. Создаем приватный конструктор, который извне не вызовется. И в него попадет экземпляр класса. Чтобы никто не смог скопировать, описываем private метод __clone. Создаем статический метод getInstance, который проверяет, есть объект класса или нет. Это типичный пример использование шаблона singleton.
Теперь, если написать: $db = new DbConn (); — выскочит ошибка, т.к. конструктор у нас защищен и не может быть вызван. Надо писать так:
$db = DbConn::getInstance; //или обращаемся напрямую $sql = SELECT * FRON table; DbConn::getInstance() -> query($sql);
Чем удобен этот метод? Например, мы работаем над большим проектом. Я пишу какой-то кусок кода, я пишу соединение с базой. Но кто знает, может мой код уже будет работать в какой-то части, там другой модуль, там другой разработчик взял и установил то же самое соединение с той же базой. Т.е. получится, что у нас порождено много объектов — экземпляров этого класса. В этом нет никакого смысла.