2008-08-25 4 views
35

Предположим, что я пишу класс PHP (> = 5.0), который должен быть одноэлементным. Все документы, которые я прочитал, говорят, чтобы сделать конструктор класса закрытым, чтобы класс не мог быть непосредственно создан.В классе PHP5, когда вызывается частный конструктор?

Так что, если у меня есть что-то вроде этого:

class SillyDB 
{ 
    private function __construct() 
    { 

    } 

    public static function getConnection() 
    { 

    } 
} 

Есть ли случаи, когда __construct() называется исключением, если я делаю

new SillyDB() 

вызов внутри самого класса?

И почему я могу создать экземпляр SillyDB внутри себя?

ответ

61

__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 за раз.

0

Небольшой выбор: для полноты вы, вероятно, объявите класс окончательным, так как вы не хотите, чтобы кто-то подклассифицировал этот класс и реализовал свой собственный публичный конструктор.

(Прости меня, если компилятор ловит подмену частного конструктора, но я не думаю, что он делает)

+2

Это комментарий, а не ответ, но хорошая точка – 2014-06-24 11:36:15

2

тест код, Марк, и дайте мне знать, что вы узнали.

EDIT: Кроме того, в этой конкретной ситуации я не уверен, почему вам нужно будет беспокоиться о том, чтобы препятствовать тому, чтобы человек был подклассифицирован. Если у кого-то есть доступ к вашему PHP-коду для подкласса, то у них также есть доступ к вашему коду, чтобы скопировать его и изменить модификаторы доступа на то, что они (по какой-либо причине) находят подходящим.

Практическая полезность Singleton в этом случае заключается в том, что, используя это, вы можете гарантировать, что вы всегда используете одно и то же соединение с базой данных для данного HTTP-запроса. Он это выполняет. Другой материал (с использованием final и частных конструкторов) полезен для понимания с точки зрения теории и еще более полезно знать, хотите ли вы распространять код качества API для других программистов, но в случае этого конкретного примера все ключевые слова делают добавление байтов в размер файла вашего класса.

6

Вот очень простой синглтон, который просто генерирует строка даты/времени:

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() 
    { 

    } 
} 
4

ОК, я проверил свои собственные тесты.

  • Если вы не объявляете свой собственный конструктор в подклассе, попытка его создания вызовет фатальную ошибку, поскольку она пытается вызвать конструктор суперкласса.
  • В случае соединения с БД, когда вы предположительно возвращаете (в PHP, в любом случае) экземпляр mysqli или ресурс, возвращенный функцией mysql_connect() (или какой-либо другой ссылкой на некоторые другие РСУБД), если вы отметите экземпляр private, нет угрозы кому-то подклассифицировать его и подделывать ссылку.
  • Как я уже упоминал ранее, если кто-то действительно хочет переопределить ваше поведение и сделать несколько соединений, они могут так же хорошо сделать это, написав новый класс.
Смежные вопросы