Допустим, я пишу класс PHP (> = 5.0), который должен быть синглом. Все документы, которые я прочитал, говорят, чтобы сделать конструктор класса закрытым, чтобы класс не мог быть непосредственно создан.
Поэтому, если у меня есть что-то вроде этого:
class SillyDB { private function __construct() { } public static function getConnection() { } }
Существуют ли случаи, когда __construct () вызывается иначе, чем если я делаю
new SillyDB()
вызвать внутри самого класса?
И почему мне разрешено создавать экземпляр SillyDB внутри себя?
__construct()
только в том случае, если вы вызвали его из метода для класса, содержащего частный конструктор. Итак, для вашего Singleton у вас может быть такой метод:
class DBConnection { private static $Connection = null; public static function getConnection() { if(!isset(self::Connection)) { self::Connection = new DBConnection(); } return self::Connection; } private function __construct() { } } $dbConnection = DBConnection::getConnection();
Причина, по которой вы / хотите создать экземпляр класса внутри себя, состоит в том, чтобы вы могли проверить, чтобы в любой момент времени существовал только один экземпляр. В конце концов, это цель Синглтона. Использование Singleton для подключения к базе данных гарантирует, что ваше приложение не будет создавать тонну соединений DB за раз.
Вот очень простой синглтон, который просто генерирует строку даты / времени:
class TheDate { private static $DateInstance = null; private $dateVal; public static function getDateInstance() { if(!isset(self::$DateInstance)) { self::$DateInstance = new TheDate(); } return self::$DateInstance; } public static function getDateVal() { return self::$DateInstance->dateVal; } private function __construct() { $this->dateVal = strftime("%Y-%m-%d %H:%M:%S"); } }
Выполнение чего-то подобного явно дает мне ту же дату снова и снова:
$date1 = TheDate::getDateInstance(); echo $date1->getDateVal() . "<br />"; $date2 = TheDate::getDateInstance(); echo $date2->getDateVal() . "<br />";
И это не вызывает ошибок:
class NewDate extends TheDate { public function __construct() { } }
Хорошо, я провела тесты самостоятельно.
mysql_connect()
(или какой-либо другой ссылкой на некоторые другие СУБД), пока вы отмечаете экземпляр private, нет угрозы, чтобы кто-то подклассифицировал его и искал ссылку. Проверьте код, Марк, и дайте мне знать, что вы узнали.
EDIT: Кроме того, в этой конкретной ситуации я не уверен, почему вам нужно будет беспокоиться о том, чтобы препятствовать человеку в подклассе. Если у кого-то есть доступ к вашему PHP-коду для подкласса, то у них также есть доступ к вашему коду, чтобы скопировать его и изменить модификаторы доступа на то, что они (по какой-либо причине) находят подходящим.
Практическая полезность Singleton в этом случае заключается в том, что, используя это, вы можете гарантировать, что вы всегда используете одно и то же соединение с базой данных для данного HTTP-запроса. Он это выполняет. Другой материал (с использованием final
и частных конструкторов) полезен для понимания с точки зрения теории и еще более полезно знать, хотите ли вы распространять код качества API для других программистов, но в случае этого конкретного примера все ключевые слова делают добавление байтов в размер файла вашего класса.
Небольшая выборка: для полноты вы, вероятно, объявите класс окончательным, так как вы не хотите, чтобы кто-то подклассифицировал этот класс и реализовал свой собственный публичный конструктор.
(Простите меня, если компилятор ловит переопределение частного конструктора, но я не думаю, что это так)