2010-03-28 7 views
6

Wenn ein Singleton in PHP erstellen, stelle ich sicher, dass es nicht, indem Sie folgende instanziiert werden kann:Kann ich eine abstrakte Klasse anstelle eines privaten __construct() beim Erstellen eines Singletons in PHP verwenden?

class Singleton { 

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

    public static function getInstance() {} 
} 

Allerdings habe ich festgestellt, dass eine Klasse als ‚abstrakten‘ definiert, bedeutet, dass es nicht instanziiert werden kann. So ist es etwas falsch mit dem Tun der folgenden statt:

abstract class Singleton { 

    public static function getInstance() {} 
} 

Das zweite Szenario ermöglicht es mir weniger Codezeilen zu schreiben, die schön wären. (Nicht, dass es tatsächlich macht einen großen Unterschied.)

+0

Cool, nicht wusste, über abstrakt in PHP, es mit PHP5 eingeführt wurde, haben die Jungs keine Zeit, immer das Hinzufügen neue coole Features. Danke und +1 für das Posten einer so interessanten Frage. –

+1

@Marco PHP 5 wurde seit Juli 2004, vor 7 Jahren, veröffentlicht. Nicht wirklich ein neues Feature. – stefgosselin

Antwort

10

Wenn ein Singleton in PHP erstellen, die __construct und __clone als private sorgt erklärt, dass die Klasse von außen nicht instanziiert werden kann: es immer noch aus dem Inneren ihrer Erklärung instanziiert werden kann.

Bei der Deklaration einer Klasse als abstract, kann es überhaupt nicht instanziiert werden; nicht einmal von innerhalb seiner Erklärung.

Das bedeutet, dass Ihre Lösung nicht funktionieren würde: Im zweiten Fall kann Ihre Methode getInstance() die Klasse nicht installieren, während dies im ersten Fall möglich ist.

2

Nein, denn dann können Sie nicht die Klasse überhaupt instanziiert (auch nicht in der statischen getInstance-Methode). Der private Konstruktor im Singleton-Beispiel stellt lediglich sicher, dass nur die statische getInstance-Methode aus derselben Klasse auf den Konstruktor zugreifen kann.

0

Es könnte funktionieren, wenn Ihr Singleton::getInstance() soll eine Instanz einer anderen Klasse zurückzukehren.

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

Aber ich würde das verwirrend finden. Ein bisschen wie der Missbrauch abstract, um die Komplexität einer abstrakten Fabrik mit den Beschränkungen eines Singleton zu kombinieren.

1

Nein, man kann nicht eine abstrakte Klasse anstelle eines privaten __construct() verwenden, wenn ein Singleton zu schaffen. Aber wenn Ihre Absicht ist es, eine Zusammenfassung Singleton zu schaffen, von dem aus zu erweitern, können Sie dies wie folgt aus:

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

Sie können dann von Singleton wie folgt erweitern:

class Foo extends Singleton { 

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

und

class Bar extends Singleton { 

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

und Manipulieren:

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

Beachten Sie jedoch, dass Singletons sehr schwierig zu testen sind und wenn möglich vermieden werden sollten.Siehe meine Antwort hier für einige Hintergrund:

+0

Ich habe nicht versucht, eine abstrakte Singleton-Klasse zu erstellen, aber ich bin mir sicher, dass jemand das nützlich finden wird, danke. Ich bin mir der Probleme von Singletons bewusst und bevorzuge die Verwendung von DI oder statischen Registern und Fabriken; Diese Frage sollte meine Neugier befriedigen! Allerdings hätte ich meine Idee eindeutig testen sollen, wie man an den anderen Kommentaren erkennen kann. –

+1

+1 für ein perfekt verwendbares Beispiel für etwas, das man nicht verwenden sollte (http://c2.com/cgi/wiki?SingletonsAreEvil). – stefgosselin

Verwandte Themen