2010-03-28 8 views
6

Al crear un Singleton en PHP, que aseguran que no se pueden crear instancias de la siguiente manera:¿Puedo usar una clase abstracta en lugar de una __construct() privada al crear un singleton en PHP?

class Singleton { 

    private function __construct() {} 
    private function __clone() {} 

    public static function getInstance() {} 
} 

Sin embargo, me di cuenta de que la definición de una clase como 'abstracta' significa que no se pueden crear instancias. Entonces, ¿hay algo malo en hacer lo siguiente en su lugar:

abstract class Singleton { 

    public static function getInstance() {} 
} 

El segundo escenario me permite escribir menos líneas de código que estaría bien. (No es que realmente signifique mucha diferencia).

+0

fresca, no sabía nada de abstracto en PHP, que se introdujo con PHP5, esos tipos no perder el tiempo, siempre añadiendo nuevas y geniales funciones Gracias y +1 por publicar una pregunta tan interesante. –

+1

@Marco PHP 5 ha estado en funcionamiento desde julio de 2004, hace 7 años. No es realmente una característica nueva. – stefgosselin

Respuesta

10

Al crear un producto único en PHP, declarando la __construct y __clone como privadas asegura que la clase no puede ser instanciado desde el exterior: todavía puede ser instanciado desde el interior de su declaración.

Al declarar una clase como abstract, no puede ser instanciado en absoluto; ni siquiera desde adentro de su declaración.

Esto significa que su solución no funcionaría: en el segundo caso, su método getInstance() no podrá instanciar la clase, mientras que sí puede hacerlo en el primer caso.

2

No porque entonces no se puede crear una instancia de la clase (ni siquiera en el método estático getInstance). El constructor privado en el ejemplo singleton simplemente asegura que solo el método getInstance estático de la misma clase puede acceder al constructor.

0

Podría funcionar si se supone que su Singleton::getInstance() devuelve una instancia de una clase diferente.

abstract class Singleton { 
    public static function getInstance() { 
    static $instance = null; 
    if (is_null($instance)) { 
     $instance = new StdClass; // a different class than 'abstract class Singleton' 
     $instance->x = time(); 
    } 
    return $instance; 
    } 
} 

$obj = Singleton::getInstance(); 

Pero me parecería confuso. Un poco como usar mal abstract para combinar la complejidad de una fábrica abstracta con las restricciones de un singleton.

1

No, no puede usar una clase abstracta en lugar de una __construct() privada al crear un singleton. Pero si su intención es crear un Singleton abstracta desde la cual se extienden desde, puede hacerlo de esta manera:

abstract class Singleton 
{ 
    private static $_instances; 
    public static function getInstance() 
    { 
     $className = get_called_class(); // As of PHP 5.3 
     if(! isset(self::$_instances[$className])) { 
     self::$_instances[$className] = new $className(); 
     } 
     return self::$_instances[$className]; 
    } 
    protected function __construct() {} 
    final private function __clone() {} 
    final private function __wakeup() {} 
} 

A continuación, puede extenderse desde Singleton así:

class Foo extends Singleton { 

    protected $_foo = 1; 
    public function setFoo($i) { $this->_foo = $i; } 
    public function getFoo() { return $this->_foo; } 
} 

y

class Bar extends Singleton { 

    protected $_foo = 1; 
    public function setFoo($i) { $this->_foo = $i; } 
    public function getFoo() { return $this->_foo; } 
} 

y manipulación:

$foo1 = Foo::getInstance(); 
$foo1->setFoo(5); 

$foo2 = Foo::getInstance(); 
var_dump($foo2); 

$bar1 = Bar::getInstance(); 
var_dump($bar1); 

echo new ReflectionObject($foo2); 
echo new ReflectionObject($bar1); 

Sin embargo, tenga en cuenta que los Singleton son muy difíciles de probar y que deben evitarse si es posible.Véase mi respuesta aquí para algunos antecedentes:

+0

No estaba intentando crear una clase de singleton abstracta, pero estoy seguro de que alguien lo encontrará útil así que gracias. Soy consciente de los problemas de Singletons y prefiero usar DI o registros y fábricas estáticos; ¡esta pregunta era para satisfacer mi curiosidad! Sin embargo, claramente debería haber probado mi idea primero, como se puede deducir de los otros comentarios. –

+1

+1 para un ejemplo perfectamente útil de algo [uno no debería usar] (http://c2.com/cgi/wiki?SingletonsAreEvil). – stefgosselin

Cuestiones relacionadas