Warum Singletons?
-
Simon2 schrieb:
Ein static an sich ist leider nicht threadsafe (sagt Matthew Wilson in "Imperfect C++")
Ein Singleton ansich ist auch nicht Threadsafe...
-
Hallo,
ganz einfach weil du bei lauter statischen Methoden eine noch viel höhere Kopplung erzielst, als es das Singleton ohnehin schon hat. Beim Singleton bestehen aber noch Möglichkeiten, wie das Implementieren einer Schnittstelle, zur Auflösung dieser Kopplung.
class Printer { public: virtual void printDocument(Document document) = 0; }; class LocalPrinter : Printer { private: LocalPrinter() { } public: virtual void printDocument(Document document) { // ... } static LocalPrinter& getInstance() { static LocalPrinter printer; return printer; } }; void printReports(Printer printer) { // ... } // anschließend der Aufruf: printReports(LocalPrinter::getInstance());
-
Das mit dem Initialisieren ist schonmal ne interessante Sache...
Bei einem Singelton werden alle Membervariablen zum gleichen Zeitpunkt initialisiert, ohne dass ich mir darüber Gedanken machen muß. Verwende ich n statische Variablen ist nicht definiert in welcher Reihenfolge diese initialisiert werden. Darum muß ich mich kümmern.
Singeltons müssen außerdem nicht zwingend beim Programmstart erzeugt und erst beim Programmende gelöscht werden. Wenn ich solche Objekte gerade nicht benötige kann ich sie löschen und bei Bedarf wieder erzeugen. Ich kann das Objekt auch als ganzes verwerfen und mir ein vollkommen anderes erzeugen.

-
Ich persönlich spar mir auch gerne das getInstance:
weil du dann auch alle daten static machen muesstest, dabei ist dann die initialisierung erst ausgefuehrt wenn du diese daten zum ersten mal verwendest und bei singletons moechte man ja gerade, dass beim ersten zugriff alle daten/member initialisiert sind.
nicht Zwangsläufig:
class MySingleton { public static PrintSingletonData(void) { cout << "My Singeltons data : " << m_Singelton.m_iSomeSingletonData << endl; } private: MySingleton() : m_iSomeSingletonData(0){} MySingleton m_Singelton; int m_iSomeSingletonData; }; MySingleton MySingleton::m_Singelton;Ich denke auch, das denjenigen, der das Singleton benutzt eigentlich die Instanz nicht interessieren sollte, sonder eher, was es tut.
@unkreativ003
Bei Deinem Beispiel fehlt die Implementierung von printReports und dort hast du dann eine Kopplung an Printer - gut: zugegeben, an einer Stelle zentral gekapselt.
-
TheBigW@Work schrieb:
@unkreativ003
Bei Deinem Beispiel fehlt die Implementierung von printReports und dort hast du dann eine Kopplung an Printer - gut: zugegeben, an einer Stelle zentral gekapselt.Die Kopplung zur "Schnittstelle" Printer ist ja auch egal, schon alleine weil eine Abhängigkeit zu einer Schnittstelle nicht zusätzlich auch noch transitive Abhängigkeiten mit sich bringt. Das Angenehme an dieser Vorgehensweise ist ja, dass das Singleton ersetzt werden kann, beispielsweise beim Testen. Gerade in Komponententests sind Singletons, bzw. singleton-ähnliche Konstruktre pures Gift, da man sie nicht durch Mock-Objekte oder ähnliches ersetzen kann.
-
Damit ich das Singleton austauschen kann muss ich ja ein interface zurückgeben und irgendwie wird dann das Singleton immer mehr zur Factory
-
Das Singleton-Muster wird zu 95% falsch eingesetzt.
-
Shade Of Mine schrieb:
Simon2 schrieb:
Ein static an sich ist leider nicht threadsafe (sagt Matthew Wilson in "Imperfect C++")
Ein Singleton ansich ist auch nicht Threadsafe...
Das wissen aber viele nicht.
Bei einem Singleton ist auch klar, dass man nur entsprechende Memberfunktionen zugreift und dabei eine gewisse Funktionalität bereitstellt (zu der auch Serialisierung gehören kann).
WENN außerdem später doch ein Multithreading unterstützt werden soll, muß man beim singleton nur die Zugriffsfunktionen anpassen, während man bei einem "einfachen static" jeden einzelnen Zugriff rauspulen muß ...Gruß,
Simon2.
-
wisser schrieb:
Das Singleton-Muster wird zu 95% falsch eingesetzt.
99% der Thesen Unregistrierter sind zu schwach begründet.
Gruß,
Simon2.
-
Najo da hat er aber schon recht.
Und wie gesagt ein Singleton ist von Haus aus auch nicht threadsafe...
-
nep schrieb:
Najo da hat er aber schon recht...
Ich aber auch ! :p
BTW: Hat hier eigentlich irgendjemand behauptet, singletons seien von sich aus threadsafe ?
Solange das nicht der Fall ist, kann man vielleicht seine Gebetsmühlen wieder einpacken und mit diskutieren anfangen (wer will).Gruß,
Simon2.
-
3Fragezeichen schrieb:
Damit ich das Singleton austauschen kann muss ich ja ein interface zurückgeben und irgendwie wird dann das Singleton immer mehr zur Factory
Ansatzweise richtig erkannt, aber es liegt vielmehr daran, dass man das Singleton bei einer Schnittstelle nicht mehr direkt verwendet, sondern sich beispielsweise als Parameter übergeben lässt, wodurch also auch keine Notwendigkeit für den globalen Zugriff gegeben ist. Ich selbst geh auch immer öfter in Richtung Factory, die ich wenn nötig einfach zusätzlich entsprechend dekoriere, so dass nur eine Instanz erstellt wird. Ansich ist diese Grundsatzfrage vergleich mit der Frage um die Abhängigkeitsauflösung (Inversion of Control oder Service Locator).
Das Problem beim Singleton ist ja wie bereits erwähnt einfach, dass es zu leichtfertig verwendet wird. Die Vernetzung einzelner Software-Komponenten gestaltet sich oft aufgrund falscher Design-Maßnahmen als schwierig. "Dank" dem globalen Zugriff eines Singletons kann man diesen falschen Design-Maßnahmen entgegenwirken, zahlt aber einen sehr teueren Preis - hohe Kopplung. Wenn man allerdings zu Beginn schon nicht das richtige Design gewählt hat, wird einem diese zusätzliche Kopplung aber auch egal sein.
-
Simon2 schrieb:
WENN außerdem später doch ein Multithreading unterstützt werden soll, muß man beim singleton nur die Zugriffsfunktionen anpassen, während man bei einem "einfachen static" jeden einzelnen Zugriff rauspulen muß ...
Ne.
Du musst jede Methode synchronisieren. Es mag einige tricks geben wie zB Adapter, die dir das bei einem Singleton erleichtern, aber du musst jede Methode abwaegen und synchronisieren. getInstance() zu synchronisieren reicht nicht aus.
@TheBigW:
doof nur dass du damit keine Objekte mehr rumreichen kannst.
-
Löscht ihr singletons wieder? Was bringt das eigentlich? Es bleibt ja bis zum Programmende immer das selbe und wird dann vomOS automatisch gelöscht.
-
Warum bleibt es bis Programmende das Selbe?
-
andere frage schrieb:
Löscht ihr singletons wieder? Was bringt das eigentlich? Es bleibt ja bis zum Programmende immer das selbe und wird dann vomOS automatisch gelöscht.
nö. ich lösche singletons nicht. globale statische variablen sind für mich auch eine sorte singletons.
bei korrekt implementioerten singletons löscht c++ die irgendwie automatisch. gelöscht müssen sie aber werden bevor das bs den speicher wegräumen darf. zu leicht baut man später ein, daß das gesiglete objekt am ende eine datei schließen muss oder dergleichen.
-
doof nur dass du damit keine Objekte mehr rumreichen kannst.
@Shade
Naja, kommt doch auf den Anwendungsfall an, oder? Wenn ich ein Singleton habe, was nur eine public Memberfunktion hat, dann nervt es sicher (aus Anwendersich) auf Dauer, wenn ich immer erst meine Instanz holen muß. Wer sagt, das ich es unbedingt als Objekt herumreichen will/muß?
Ansich zeigt diese Diskussion doch nur, dass es DAS Singleton so im Detail nicht giebt. Sei es das Thema initialisierung/deinitialisierung, Zugriff oder was auch immer. Singleton sagt eben nur etwas über die Instanziierbarkeit aus und läßt die anderen Details im Dunkeln.
-
DAS Singleton gibt es sehr wohl und ist in einschlägiger Literatur beschrieben. Es ist halt ein Muster aus der Objektorientierten Programmierung und wird daher auch als Objekt behandelt. Nur weil DU der Meinung bist, ein Singleton nicht als Objekt zu verwenden, heisst das noch lange nicht, dass ein Singleton mehrdeutig ist.

Es bringt halt Vorteile mit sich, dass ein Singleton als Objekt behandelt wird. Du kannst das Objekt im Nachhinein spezialisieren, indem Du davon ableitest. Du kannst bei Bedarf refactorn, falls Du doch mal mehrere Instanzen erlauben willst. usw...
Wenn Du die Funktionalität statisch bereit stellst, dann kannst Du sie nie im Nachhinein polymorph überschreiben. -> unflexibel
-
So war das gar nicht gemeint. Es ging mir eher darum, das bei Singleton nicht automatisch das immer gleiche Vorgehen gemeint ist: ein Meyers Singleton und ein Phoenix Singleton sind nunmal unterschiedlich und trotzdem beide Singletons.
Es geht mir auch nicht darum hier zu sagen, das immer alle member statisch sein sollen. Ich sage nur, das es Fälle giebt wo das durchaus Sinn machen kann. Es schließt ja nicht mal aus, das man die Instanz trotzdem durch die Gegend reicht.
-
Mathias schrieb:
Warum bleibt es bis Programmende das Selbe?
Weil das doch gerade der Sinn des Singleton ist.