Die Antwort unten ist falsch, aber ich werde sie behalten, damit andere daraus lernen können (siehe unten).
In ExampleAkönnen Sie dieselbe ConfigInstanz für mehrere Klassen verwenden. Sollte es jedoch nur eine ConfigInstanz in der gesamten Anwendung geben, sollten Sie das Singleton-Muster anwenden Config, um zu vermeiden, dass mehrere Instanzen von vorhanden sind Config. Und wenn Configes 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 Configfü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
ExampleXeine separate Instanz von haben sollte Config, gehen Sie mit ExampleB;
- Wenn jede Instanz von
ExampleXeine (und nur eine) Instanz von gemeinsam Confignutzt, verwenden Sie ExampleA with Config Singleton;
- Wenn Instanzen von
ExampleXunterschiedliche Instanzen von verwenden können Config, bleiben Sie bei ExampleA.
Warum die Konvertierung Configin 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 ExampleAein eigener Verweis auf die ConfigInstanz abgerufen wird , werden die Klassen eng gekoppelt. Es wird keine Möglichkeit geben, eine Instanz ExampleAzu haben, um eine andere Version von Config(sagen wir einige Unterklassen) zu verwenden. Dies ist schrecklich, wenn Sie ExampleAeine Mock-up-Instanz von testen möchten, Configda es keine Möglichkeit gibt, sie bereitzustellen ExampleA.
Die Prämisse davon wird es eine und nur eine Instanz geben, die Configvielleicht 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 Configwünschenswert sind, gibt es keine Möglichkeit, dies zu erreichen, ohne den Code neu zu schreiben.
Auch wenn die einzige Instanz von Configmö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 staticMethode ist, gibt es keine Möglichkeit, die Unterklasse abzurufen. Auch hier muss der Code neu geschrieben werden.
Die Tatsache, dass ExampleAverwendet Configwird, 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, Configohne die Implementierung jeder anderen Klasse zu untersuchen.
Auch wenn die Tatsache, dass ExampleAein 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.