2011-09-10 16 views
6

Todos los patrones singleton que he visto utilizan una referencia al objeto para determinar si el objeto ha sido instanciado. Sin embargo, si estoy usando un singleton para garantizar solo una conexión db, ¿por qué no utilizar el enlace de recursos de conexión db para hacer esto? Aquí está el código que estoy usando. (PD: funciona bien). Uso el comentario para poder buscar mis clases fácilmente.Un singleton más simple

/*one*/ 

class one 
    { 
    public static $db; 
    private function __construct() 
    { 
    self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
    } 
    public static function get() 
    { 
    if(self::$db==NULL) 
     { 
     new self(); 
     } 
    return self::$db; 
    } 
    } 
+1

+1 por el ingenio! – Clive

+1

Todavía es singleton. Nada inusual allí, diría yo. – Smar

+2

Errr ... ¿Nadie ve que el método get devuelve un objeto diferente? – Macmade

Respuesta

5

En PHP, un constructor no vuelve.

Así que su método get devuelve un objeto one, la primera vez que se lo llama, y ​​luego un objeto mysqli. Probablemente no es lo que quieres.

if(self::$_db == NULL) 
{ 
    return new self(); // Here you return an object of class one 
} 
else 
{ 
    return self::$_db; // Here you return an object of type mysqli 
} 

Si desea devolver el objeto mysqli, no es necesario un producto único, ya que no hay necesidad de crear una instancia de un objeto que está aquí sólo para devolver una instancia de otro objeto.

El patrón de registro sería mejor en tal caso.

Si necesita proporcionar métodos (un contenedor para su objeto de base de datos), cree un singleton real.

EDITAR

revisar su código actualizado. Ahora devuelve siempre la instancia mysqli. Pero no necesitas crear una instancia de tu propio objeto. Eso es completamente inútil ...

Si realmente quiere ir con su tipo de patrón, como se dijo, en su instancia estática, comprueba si self::db es NULL. En caso afirmativo, crea la instancia mysqli y asígnela al self::db. Luego lo devuelve.

public static getDatabaseInstance() 
{ 
    if(self::$_db == NULL) 
    { 
     self::$_db = new mysqli(...); 
    } 

    return self::$_db; 
} 

También establezca el constructor en privado, por lo que los usuarios no podrán crear instancias inútiles de su clase. O mejor hacerlo público y lanzar una excepción:

public function __construct() 
{ 
    throw new Exception('This class is not supposed to be instantiated'); 
} 
+0

De la documentación de PHP: 'void __construct ([mixed $ args [, $ ...]])'. Ver el 'void'? http://php.net/manual/en/language.oop5.decon.php – Macmade

+1

Significa que el valor de retorno se ignora. Entonces, incluso si devuelve algo (otro objeto), no modificará el tipo de objeto instanciado por 'nuevo'. – Macmade

+0

Ver mi edición ...:) – Macmade

0
class one 
{ 
    private static $_selfInstance; 
    public $db; 
    private function __construct() 
    { 
    } 
    public function getDb() 
    { 
     if($this->db == null) 
     $this->db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
     return $this->db; 

    } 

    public static function getInstance() 
    { 
     if(!(self::$_selfInstance instanceof self)) { 
     self::$_selfInstance= new self(); 
     } 
     return self::$_selfInstance; 
    } 
} 

acceso

$db = one::getInstance()->getDb(); 
+1

¿Hubo alguna razón para dejar el segundo 'n' en' $ _selfInstace'? – jcolebrand

1

Suponiendo que estoy analizar bien su pregunta, usted está preguntando si es apropiado el uso de la nulidad de $db para asegurarse de que sólo una instancia uno; esa es una manera perfectamente válida de hacer las cosas, y de hecho es lo que recomendaría. PHP null está explícitamente diseñado para representar una variable con "sin valor", una combinación perfecta para el estado no inicializado del patrón singleton.

Normalmente, estas cosas solo se llamarán por un nombre intuitivo, p. Ej. SomeAppDbConn.

0

Como ya señaló Macmade, el método constructor no devuelve nada más que una instancia de la clase. Suponiendo que siempre desee la misma instancia de mysqli, así es como lo haría.

class DBInstance 
{ 
    protected static $db; 

    private function __construct() 
    { 
     // intentionally empty 
    } 

    public static function get() 
    { 
     if(self::$db === NULL) 
     { 
      self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
     } 

     return self::$db; 
    } 
} 

Sin duda es un patrón singleton con una ventaja adicional de separar la creación de instancias de la clase instanciada.

+0

Un registro sería mejor, en mi humilde opinión. O al menos, declara que el constructor es privado, para evitar instancias inútiles de la clase. – Macmade

+0

Usted es y estoy de acuerdo con usted en el uso del registro. Por otro lado, usar este método es ciertamente más rápido si está desarrollando una aplicación realmente pequeña en la que una conexión a la base de datos es la única que cabe en este patrón. ¿Qué piensas? – gilden

+0

Claro, y parece que él lo quiere de esa manera ...:) – Macmade

3

Definir funciona bien :)

Tratar de:

  • comparar los hashes de objetos devueltos por los dos métodos (no importa cuando se utiliza la clonación objeto)
  • conectarse a DB usando credenciales diferentes (por ejemplo, en las pruebas unitarias)
  • desconectarse del DB y reconectar nuevamente
  • restablecer la instancia del objeto (ahora la creación de 1000 objetos con new llena la memoria)
  • decirle a otro desarrollador para crear en la instancia de esta clase, que seguramente buscará el método one::getInstance(). ¿Cómo adivina el comportamiento de esta clase?

Los singleton son sobre el estado global. Parece que aquí tienes un estado global + un poco de desorden.