Практически в каждом объектно-ориентированном приложении есть классы, экземпляры которых мы создаём по несколько раз за время выполнения скрипта, например, подключение к базе данных.
Но зачем мы делаем такие нагрузочные для PHP операции? Ведь если подключение к БД было установлено, зачем его закрывать, а через мгновение снова открывать? В неопытных программистов такие операции происходят по несколько раз за один запрос. В идеале я вижу такой сценарий исполнения скрипта:
1. Создали подключение к базе данных;
2. Использовали его во всех нужных местах нашего приложения;
3. Закрыли соединение с базой данных.
Ваше приложение просто может вновь и вновь использовать экземпляр уже созданного класса. А как же не допустить создание новых экземпляров класса, если например, другой класс, не знает было ли до этого установлено соединение с БД, которую он использует? Если соединение было установлено, то где его «взять»? Сегодня я расскажу Вам как грамотно и профессионально решить подобную задачу.
Решение
Конечно, Вы можете сказать мне, что решение уже есть и выдумывать ничего не надо – глобальные переменные. Действительно, Вы вполне сможете использовать глобальные переменные для решения подобных проблем, но их использование неудобное и не грамотное решение.
Любой Ваш скрипт сможет поменять глобальную переменную, заменить её значение на другое значение и т.д. Вообще, я не хочу углубляться, поэтому я предлагаю Вам почитать о глобальных переменных в сети: вот тут.
Когда Вы хотите быть уверенными, что создается лишь один экземпляр конкретного класса в Вашем приложении, Вам необходимо использовать т.н. «шаблон проектирования» Singleton(Одиночка). Суть работы класса, который реализует данный паттерн, очень проста:
1. Закрываем доступ к функциям __construct() и __clone(), используя ключевое слово private;
2. Объявляем статическую защищенную переменную $_instance нашего класса;
3. Создаём «public static» метод класса getInstance(), который будет возвращать нам экземпляр класса.
Как Вы можете сами увидеть, реализовать шаблон проектирования Singleton очень просто. Нужно только хорошо знать объектно-ориентированное программирование, чтобы умело оперировать уровнем доступа к функциям и переменным класса, дабы защитить их от ненормативного использования.
Ниже приведен пример класса, который реализует паттерн Singleton:
Давайте разберём пошагово весь написанный код. Вначале кода мы объявляем класс SingletonTest. В объявленном классе создаём защищенную статическую переменную $_instance, в которой мы храним экземпляр класса. Далее делаем невозможным вызов функций __construct() и __clone() вне класса (т.е. не можно будет применить к классу оператор new).
Следующий шаг – дело техники. Функция getInstance(). Данная функция объявлена как статическая и общедоступная, поэтому мы можем вызывать её, даже не создавая экземпляр класса. Функция проверяет, есть ли у нас уже созданный экземпляр класса. Если есть – возвращает его, а если нет – создаёт новый экземпляр, сохраняя его в статической переменной, и потом возвращает его.
При этом конструктор и деструктор класса выполняются по одному разу, а это очень удобно использовать в своих нуждах (напр. закрыть/открыть файл, подключить/отключить БД и т.д.).
Делаем выводы
Итак, у нас есть изящное решение и если его мы сможем использовать правильно, то сможем добиться успеха.
Но зачем мы делаем такие нагрузочные для PHP операции? Ведь если подключение к БД было установлено, зачем его закрывать, а через мгновение снова открывать? В неопытных программистов такие операции происходят по несколько раз за один запрос. В идеале я вижу такой сценарий исполнения скрипта:
1. Создали подключение к базе данных;
2. Использовали его во всех нужных местах нашего приложения;
3. Закрыли соединение с базой данных.
Ваше приложение просто может вновь и вновь использовать экземпляр уже созданного класса. А как же не допустить создание новых экземпляров класса, если например, другой класс, не знает было ли до этого установлено соединение с БД, которую он использует? Если соединение было установлено, то где его «взять»? Сегодня я расскажу Вам как грамотно и профессионально решить подобную задачу.
Решение
Конечно, Вы можете сказать мне, что решение уже есть и выдумывать ничего не надо – глобальные переменные. Действительно, Вы вполне сможете использовать глобальные переменные для решения подобных проблем, но их использование неудобное и не грамотное решение.
Любой Ваш скрипт сможет поменять глобальную переменную, заменить её значение на другое значение и т.д. Вообще, я не хочу углубляться, поэтому я предлагаю Вам почитать о глобальных переменных в сети: вот тут.
Когда Вы хотите быть уверенными, что создается лишь один экземпляр конкретного класса в Вашем приложении, Вам необходимо использовать т.н. «шаблон проектирования» Singleton(Одиночка). Суть работы класса, который реализует данный паттерн, очень проста:
1. Закрываем доступ к функциям __construct() и __clone(), используя ключевое слово private;
2. Объявляем статическую защищенную переменную $_instance нашего класса;
3. Создаём «public static» метод класса getInstance(), который будет возвращать нам экземпляр класса.
Как Вы можете сами увидеть, реализовать шаблон проектирования Singleton очень просто. Нужно только хорошо знать объектно-ориентированное программирование, чтобы умело оперировать уровнем доступа к функциям и переменным класса, дабы защитить их от ненормативного использования.
Ниже приведен пример класса, который реализует паттерн Singleton:
<?php
/**
* Простой пример реализации паттерна Singleton
*
* @name SingletonTest
* @author Andrew Vasiliev (illusive [at] meta [dot] ua)
*/
class SingletonTest
{
/**
* Статическая переменная, в которой мы
* будем хранить экземпляр класса
*
* @var SingletonTest
*/
protected static $_instance;
/**
* Закрываем доступ к функции вне класса.
* Паттерн Singleton не допускает вызов
* этой функции вне класса
*
*/
private function __construct(){
/**
* При этом в функцию можно вписать
* свой код инициализации. Также можно
* использовать деструктор класса.
* Эти функции работают по прежднему,
* только не доступны вне класса
*/
}
/**
* Закрываем доступ к функции вне класса.
* Паттерн Singleton не допускает вызов
* этой функции вне класса
*
*/
private function __clone(){
}
/**
* Статическая функция, которая возвращает
* экземпляр класса или создает новый при
* необходимости
*
* @return SingletonTest
*/
public static function getInstance() {
// проверяем актуальность экземпляра
if (null === self::$_instance) {
// создаем новый экземпляр
self::$_instance = new self();
}
// возвращаем созданный или существующий экземпляр
return self::$_instance;
}
}
?>
Давайте разберём пошагово весь написанный код. Вначале кода мы объявляем класс SingletonTest. В объявленном классе создаём защищенную статическую переменную $_instance, в которой мы храним экземпляр класса. Далее делаем невозможным вызов функций __construct() и __clone() вне класса (т.е. не можно будет применить к классу оператор new).
Следующий шаг – дело техники. Функция getInstance(). Данная функция объявлена как статическая и общедоступная, поэтому мы можем вызывать её, даже не создавая экземпляр класса. Функция проверяет, есть ли у нас уже созданный экземпляр класса. Если есть – возвращает его, а если нет – создаёт новый экземпляр, сохраняя его в статической переменной, и потом возвращает его.
При этом конструктор и деструктор класса выполняются по одному разу, а это очень удобно использовать в своих нуждах (напр. закрыть/открыть файл, подключить/отключить БД и т.д.).
Делаем выводы
Итак, у нас есть изящное решение и если его мы сможем использовать правильно, то сможем добиться успеха.