2010-03-28 9 views
6

Quando si crea un Singleton in PHP, mi assicurarsi che essa non può essere un'istanza effettuando le seguenti operazioni:Posso usare una classe astratta invece di una __construct() privata durante la creazione di un singleton in PHP?

class Singleton { 

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

    public static function getInstance() {} 
} 

Tuttavia, mi sono reso conto che la definizione di una classe come 'astratto' significa che non è possibile creare un'istanza. Quindi è qualcosa che non va a fare la seguente invece:

abstract class Singleton { 

    public static function getInstance() {} 
} 

Il secondo scenario mi permette di scrivere un minor numero di linee di codice che sarebbe bello. (Non che in realtà faccia molta differenza)

+0

fresco, non conoscevano astratta in PHP, è stato introdotto con PHP5, quei ragazzi non perdono tempo, aggiungendo sempre nuove fantastiche funzionalità. Grazie, e +1 per aver postato una domanda così interessante. –

+1

@Marco PHP 5 è uscito dal luglio 2004, 7 anni fa. Non proprio una nuova funzionalità. – stefgosselin

risposta

10

Quando si crea un singleton in PHP, dichiarare la __construct e __clone come assicura privati ​​che la classe non può essere istanziare dall'esterno: può ancora essere istanziare dall'interno sua dichiarazione.

Quando si dichiara una classe come abstract, non può essere instanzato a tutti; nemmeno da dentro la sua dichiarazione.

Ciò significa che la soluzione non funzionerà: nel secondo caso, il metodo getInstance() non sarà in grado di instanciare la classe, mentre nel primo caso può farlo.

2

No perché allora non è possibile creare un'istanza della classe (nemmeno nel metodo getInstance statico). Il costruttore privato nell'esempio singleton assicura solo che solo il metodo statico getInstance della stessa classe può accedere al costruttore.

0

Potrebbe funzionare se il tuo Singleton::getInstance() deve restituire un'istanza di una classe diversa.

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

Ma lo trovo confuso. Un po 'come abusare di abstract per combinare la complessità di una fabbrica astratta con le restrizioni di un singleton.

1

No, non è possibile utilizzare una classe astratta anziché un __construct privato() durante la creazione di un singleton. Ma se la vostra intenzione è quella di creare un estratto Singleton da cui si estendono da, è possibile farlo in questo modo:

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

È quindi possibile estendere da Singleton in questo modo:

class Foo extends Singleton { 

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

e

class Bar extends Singleton { 

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

e manipolazione:

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

Tuttavia, tieni presente che i Singletons sono molto difficili da testare unitamente e dovrebbero essere evitati se possibile.Vedere la mia risposta qui per un po 'di fondo:

+0

Non stavo tentando di creare una classe singleton astratta, ma sono sicuro che qualcuno lo troverà utile quindi grazie. Sono a conoscenza dei problemi di Singletons e preferisco usare DI o registri statici e fabbriche; questa domanda era per soddisfare la mia curiosità! Tuttavia, chiaramente avrei dovuto testare prima la mia idea come si può vedere dagli altri commenti. –

+1

+1 per un esempio perfettamente utilizzabile di qualcosa [non si dovrebbe usare] (http://c2.com/cgi/wiki?SingletonsAreEvil). – stefgosselin

Problemi correlati