Schreibweise bei Singletons
-
... das ist hier die Frage

Und in der Regel auch der Designfehler. Es geht ja darum, ob etwas nur einmal in einem Prozess existieren darf. Und das ist in den seltensten Fällen so.
Hinzu kommt, dass man das immer noch über Factory Funktionen à la
DBCache& getDBCache(const DBConnection& connection)regeln kann. Ob die intern mit einer einzelnen Instanz oder mehreren arbeiten ist dann für den Rest der Applikation egal.
-
Meiner Meinung nach werden Singletons oft missbraucht um eine Referenz auf die jeweiligen Instanz zu bekommen. Das bringt aber dasselbe Problem wie Globale Variablen mit sich. Singleton's sind ein Pattern um genau eine Instanz zuzulassen, nicht um an sie ranzukommen.
-
Exakt, man kann es gar nicht oft genug sagen. Der Sinn des Singleton Pattern ist genau eben nicht eine globale Instanz eines Objektes zur Verfügung zu stellen. Der Sinn des Singleton Pattern ist es sicherzustellen dass auf keinen Fall und überhaupt irgendwie mehr als genau eine Instanz der fraglichen Klasse erzeugt werden kann. Genau das und nur das ist der Zweck eines Singleton. Die globale Instanz ist lediglich eine Konsequenz des Pattern und nicht das wofür der Pattern gedacht ist. Man könnte jetzt darüber argumentieren inwiefern der Singleton Pattern damit überhaupt den Grundfesten der OOP widerspricht, aber das ist an dieser Stelle egal. Wichtig ist dass Singleton kein Ersatz für eine globale Variable ist, nie dafür gedacht war und ständig genau dafür verwendet wird weil es so schön einfach ist und so viele Programmierer den Pattern nicht verstanden haben.
Da ich von TextureManagern mehr verstehe (auch wenn ich von expliziten Managerklassen generell nicht viel halte, sowas macht bei mir normalerweise irgendein anderes Objekt implizit) kann ich dir versichern dass es im Allgemeinen eine sehr sehr schlechte Idee wäre einen TextureManager als Singleton anzulegen. Spätestens wenn du mehrere Bildschirme verwenden willst und damit mehrere Fenster und evtl. auch mehrere Grafikkarten verwalten musst wird ein solches Design weit über seine Grenzen strapaziert sein. Ohne Singleton ist sowas in jedem Fall viel sauberer und flexibler gelöst da auch andere Probleme wie z.B. die Frage wann wie initialisiert wird und was passiert wenn jemand vorher drauf zugreifen will gar nicht erst auftreten.
Und ich bin mir sicher dass es bei Datenbanken nicht großartig anders ausschaut. Man wird zwar sehr oft mit genau einer Datenbank arbeiten aber es wird wohl praktisch nie eine grundlegende Notwendigkeit sein dass die Möglichkeit der Existenz von zwei Datenbank Objekten mit aller Kraft unterbunden werden muss. Genau das ist es aber was man mit einem Singleton ausdrücken würde.
-
dot schrieb:
Da ich von TextureManagern mehr verstehe (auch wenn ich von expliziten Managerklassen generell nicht viel halte, sowas macht bei mir normalerweise irgendein anderes Objekt implizit) kann ich dir versichern dass es im Allgemeinen eine sehr sehr schlechte Idee wäre einen TextureManager als Singleton anzulegen. Spätestens wenn du mehrere Bildschirme verwenden willst und damit mehrere Fenster und evtl. auch mehrere Grafikkarten verwalten musst wird ein solches Design weit über seine Grenzen strapaziert sein.
Der TextureManager war auch für Files gedacht, damit man nicht x-mal texture1.bmp einliest. Der soll keine grafikkartenspezifische Texture halten.
Ohne Singleton ist sowas in jedem Fall viel sauberer und flexibler gelöst da auch andere Probleme wie z.B. die Frage wann wie initialisiert wird und was passiert wenn jemand vorher drauf zugreifen will gar nicht erst auftreten.
Wieso sollten die nicht auftreten? Du musst auch ohne Singleton deine Klasse irgendwann erzeugen und schauen wer wann und wo diese verwenden kann.
-
WieEsGeht schrieb:
Wieso sollten die nicht auftreten? Du musst auch ohne Singleton deine Klasse irgendwann erzeugen und schauen wer wann und wo diese verwenden kann.
Natürlich. Und ohne Singleton erzeuge ich meinen Texture Manager genau dann wenn es geht dort wo es geht. Das impliziert dann z.B. weiter dass Objekte die Texturen laden müssen erst erzeugt werden können wenn ein Texturemanager erzeugt ist da die schließlich eine Referenz drauf brauchen die sie natürlich im Konstruktor benötigen. Ein Singleton würde es erlauben dass ein Objekt auf den TextureManager zugreift bevor dieser noch etwas sinnvolles tun kann. Was soll in so einem Fall passieren? Gibt getInstance() einen Nullpointer zurück? Ist es eine nop? Fliegt eine Exception? Muss ich dann überall wo ich was mit dem TextureManager mache diesen Fehlerfall abfangen? Ohne Singelton stellen sich all diese Fragen gar nicht da eine solche Problemsituation by design unmöglich ist.
-
Gut, dann frag ich einfach mal so:
Wie würdet ihr denn realisieren, dass x Klassen auf eine bestimmte Instanz zugreifen? In jeder Klasse eine Referenz zu speichern erscheint mir aufwändig. Also sowas ähnliches wie(Pseudocode):MyClass::registerErrorStack( ErrorStack &ref ); ErrorStack es; MyClassA.registerErrorStack( es ); MyClassB.registerErrorStack( es );Oder ist es sowas, was ihr für sinnvoll haltet?
-
Die Antwort ist eigentlich recht simpel... parent Variable... eine ganz gängige Praxis in Qt zum Beispiel...
-
dot schrieb:
WieEsGeht schrieb:
Wieso sollten die nicht auftreten? Du musst auch ohne Singleton deine Klasse irgendwann erzeugen und schauen wer wann und wo diese verwenden kann.
Natürlich. Und ohne Singleton erzeuge ich meinen Texture Manager genau dann wenn es geht dort wo es geht. Das impliziert dann z.B. weiter dass Objekte die Texturen laden müssen erst erzeugt werden können wenn ein Texturemanager erzeugt ist da die schließlich eine Referenz drauf brauchen die sie natürlich im Konstruktor benötigen. Ein Singleton würde es erlauben dass ein Objekt auf den TextureManager zugreift bevor dieser noch etwas sinnvolles tun kann. Was soll in so einem Fall passieren? Gibt getInstance() einen Nullpointer zurück? Ist es eine nop? Fliegt eine Exception? Muss ich dann überall wo ich was mit dem TextureManager mache diesen Fehlerfall abfangen? Ohne Singelton stellen sich all diese Fragen gar nicht da eine solche Problemsituation by design unmöglich ist.
Ich weiß nicht welchen Fall es geben soll, wo ein TextureManager keine Files laden können sollte, aber wenn wir annehmen, dass es diesen gibt, dann kann ich mit oder ohne Singleton Müll programmieren und den zufrüh erzeugen. Ich kann auch ohne Singleton einen TextureManager irgendwann erzeugen und einem Objekt darauf eine Referenz geben ohne das der TextureManager funktioniert. Ich könnte sogar 100 TextureManager ohne Singleton erzeugen, so dass er im Prinzip sinnlos ist. Müll kann man immer porgrammieren, ob mit oder ohne Singleton. Ob ich einem Objekt eine Referenz übergebe oder sie über getInstance hole, ändert garnichts daran, dass es der falsche Zeitpunkt sein kann. Wenn es so einen Zeitpunkt gibt, bei dem man ein Objekt zufrüh erzeugt, dann sorgst du am besten dafür, dass die Anwendung crasht, vielleicht noch mit assert. Wer sowas programmiert, soll es auch gleich merken, da brauchst du nicht nachdenken ob man überall den Fehler behandeln muss.
-
Dazu brauche ich irgendwo genau eine Instanz die ich fragen kann, ob die Ressource schon geladen ist.
Dazu muss die Instanz aber kein Singleton sein.
-
knivil schrieb:
Dazu brauche ich irgendwo genau eine Instanz die ich fragen kann, ob die Ressource schon geladen ist.
Dazu muss die Instanz aber kein Singleton sein.
Ja, man kann auch irgendwo genau eine Instanz erstellen und die dann überall rumreichen und verwenden. Im Prinzip wie ein Singleton, nur dass man es nicht so nennt, weil sonst alle Designfehler schreien.