2008-08-25 10 views
35

Digamos que estoy escribiendo una clase de PHP (> = 5.0) que debe ser un singleton. Todos los documentos que he leído dicen que el constructor de la clase sea privado, por lo que no se puede crear una instancia directa de la clase.En una clase PHP5, ¿cuándo se llama a un constructor privado?

Así que si tengo algo como esto:

class SillyDB 
{ 
    private function __construct() 
    { 

    } 

    public static function getConnection() 
    { 

    } 
} 

¿Hay casos en los que __construct() se llama distinta si estoy haciendo una llamada

new SillyDB() 

dentro de la propia clase?

¿Y por qué puedo instanciar SillyDB desde adentro?

Respuesta

61

__construct() solo se llamaría si se llama desde un método para la clase que contiene el constructor privado. Así que para su Singleton, es posible que tenga un método de este modo:

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

La razón por la que son capaces/querría crear una instancia de la clase desde dentro de sí mismo es por lo que se puede comprobar para asegurarse de que sólo existe un caso en el en cualquier momento. Este es el objetivo de un Singleton, después de todo. El uso de un Singleton para una conexión de base de datos garantiza que su aplicación no está haciendo una tonelada de conexiones de base de datos a la vez.

0

Un pequeño truco: Para completar, usted probablemente declare la clase como final también, ya que no querría que alguien subclases esta clase e implemente su propio constructor público.

(Perdóname si el compilador llama la dominante de un constructor privado, pero no creo que lo hace)

+2

Eso es un comentario, no una respuesta, pero es un buen punto –

2

probar el código, Marcos, y quiero saber lo que descubres.

EDITAR: Además, en esta situación particular, no estoy seguro de por qué tendría que preocuparse por evitar que una persona haga subclases. Si alguien tiene acceso a su código PHP para subclasificarlo, entonces también tienen acceso a su código para copiarlo y cambiar los modificadores de acceso a algo que ellos (por cualquier razón) encuentren adecuado.

La utilidad práctica de Singleton en este caso es que, al usarlo, puede asegurarse de que siempre está utilizando la misma conexión de base de datos para una solicitud HTTP determinada. Lo logra. Las otras cosas (usando final y constructores privados) es útil saber desde una perspectiva teórica, y aún más útil saber si desea distribuir código de calidad API a otros programadores, pero en el caso de este ejemplo en particular, todas las palabras clave lo que está haciendo es agregar bytes al tamaño de su archivo de clase.

6

Aquí es un conjunto unitario muy simple que solo genera una cadena de fecha/hora:

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"); 
    } 
} 

Hacer algo como esto, obviamente, me da la misma fecha una y otra vez:

$date1 = TheDate::getDateInstance(); 
echo $date1->getDateVal() . "<br />"; 

$date2 = TheDate::getDateInstance(); 
echo $date2->getDateVal() . "<br />"; 

Y haciendo esto doesn No generar ningún error:

class NewDate extends TheDate 
{ 
    public function __construct() 
    { 

    } 
} 
4

OK, hice algunas pruebas por mi cuenta.

  • Si no declaras tu propio constructor en la subclase, intentar crear una instancia arrojará un error fatal, porque intenta llamar al constructor de la superclase.
  • En el caso de una conexión de base de datos, cuando presumiblemente está regresando (en PHP, de todos modos) una instancia mysqli o el recurso devuelto por la función mysql_connect() (o algún otro enlace a otro RDBMS), siempre que marque la instancia privada, no hay amenaza de que alguien la subclasifique y altere el enlace.
  • Como he mencionado anteriormente, si alguien realmente quiere anular su comportamiento y hacer conexiones múltiples, podría hacerlo escribiendo una nueva clase.
Cuestiones relacionadas