Die Antwort unten ist falsch, aber ich werde sie behalten, damit andere daraus lernen können (siehe unten).
In ExampleA
können Sie dieselbe Config
Instanz für mehrere Klassen verwenden. Sollte es jedoch nur eine Config
Instanz in der gesamten Anwendung geben, sollten Sie das Singleton-Muster anwenden Config
, um zu vermeiden, dass mehrere Instanzen von vorhanden sind Config
. Und wenn Config
es sich um einen Singleton handelt, können Sie stattdessen Folgendes tun:
class ExampleA
{
private $config;
public function __construct()
{
$this->config = Config->getInstance();
}
}
$exampleA = new ExampleA();
In ExampleB
, auf der anderen Seite finden Sie immer eine separate Instanz erhalten Config
für jede Instanz ExampleB
.
Welche Version Sie wirklich anwenden sollten, hängt davon ab, wie die Anwendung Instanzen von Folgendem behandelt Config
:
- Wenn jede Instanz von
ExampleX
eine separate Instanz von haben sollte Config
, gehen Sie mit ExampleB
;
- Wenn jede Instanz von
ExampleX
eine (und nur eine) Instanz von gemeinsam Config
nutzt, verwenden Sie ExampleA with Config Singleton
;
- Wenn Instanzen von
ExampleX
unterschiedliche Instanzen von verwenden können Config
, bleiben Sie bei ExampleA
.
Warum die Konvertierung Config
in einen Singleton falsch ist:
Ich muss zugeben, dass ich erst gestern etwas über das Singleton- Muster gelernt habe (Lesen des Head First- Buches mit Designmustern). Naiv ging ich herum und wandte es für dieses Beispiel an, aber wie viele darauf hingewiesen haben, ist ein Weg ein anderer (einige waren kryptischer und sagten nur "Du machst es falsch!"), Dies ist keine gute Idee. Um zu verhindern, dass andere den gleichen Fehler machen, den ich gerade gemacht habe, folgt eine Zusammenfassung, warum das Singleton- Muster schädlich sein kann (basierend auf den Kommentaren und dem, was ich beim Googeln herausgefunden habe):
Wenn ExampleA
ein eigener Verweis auf die Config
Instanz abgerufen wird , werden die Klassen eng gekoppelt. Es wird keine Möglichkeit geben, eine Instanz ExampleA
zu haben, um eine andere Version von Config
(sagen wir einige Unterklassen) zu verwenden. Dies ist schrecklich, wenn Sie ExampleA
eine Mock-up-Instanz von testen möchten, Config
da es keine Möglichkeit gibt, sie bereitzustellen ExampleA
.
Die Prämisse davon wird es eine und nur eine Instanz geben, die Config
vielleicht jetzt gilt , aber Sie können nicht immer sicher sein, dass dies auch in Zukunft der Fall sein wird . Wenn sich zu einem späteren Zeitpunkt herausstellt, dass mehrere Instanzen von Config
wünschenswert sind, gibt es keine Möglichkeit, dies zu erreichen, ohne den Code neu zu schreiben.
Auch wenn die einzige Instanz von Config
möglicherweise für alle Ewigkeit gilt, kann es vorkommen, dass Sie eine Unterklasse von verwenden möchten Config
(während Sie immer noch nur eine Instanz haben). Da der Code die Instanz jedoch direkt über getInstance()
of abruft Config
, was eine static
Methode ist, gibt es keine Möglichkeit, die Unterklasse abzurufen. Auch hier muss der Code neu geschrieben werden.
Die Tatsache, dass ExampleA
verwendet Config
wird, wird verborgen, zumindest wenn nur die API von angezeigt wird ExampleA
. Das mag eine schlechte Sache sein oder auch nicht, aber ich persönlich fühle, dass dies ein Nachteil ist. Bei der Wartung gibt es beispielsweise keine einfache Möglichkeit, herauszufinden, welche Klassen von Änderungen betroffen sind, Config
ohne die Implementierung jeder anderen Klasse zu untersuchen.
Auch wenn die Tatsache, dass ExampleA
ein Singleton verwendet Config
wird, an sich kein Problem darstellt, kann es aus Testsicht immer noch zu einem Problem werden. Singleton- Objekte tragen den Status, der bis zur Beendigung der Anwendung bestehen bleibt. Dies kann ein Problem sein, wenn Unit-Tests ausgeführt werden, da ein Test von einem anderen isoliert werden soll (dh, dass die Ausführung eines Tests das Ergebnis eines anderen Tests nicht beeinflussen sollte). Um dies zu beheben, muss das Singleton- Objekt zwischen jedem Testlauf zerstört werden (möglicherweise muss die gesamte Anwendung neu gestartet werden), was zeitaufwändig sein kann (ganz zu schweigen von langwierig und ärgerlich).
Trotzdem bin ich froh, dass ich diesen Fehler hier gemacht habe und nicht bei der Implementierung einer echten Anwendung. Tatsächlich dachte ich darüber nach, meinen neuesten Code neu zu schreiben, um das Singleton- Muster für einige der Klassen zu verwenden. Obwohl ich die Änderungen leicht rückgängig machen könnte (natürlich ist alles in einem SVN gespeichert), hätte ich trotzdem Zeit damit verschwendet.