Warum einen Singleton anstelle statischer Methoden verwenden?


92

Ich habe nie gute Antworten auf diese einfachen Fragen zu Hilfs- / Dienstprogrammklassen gefunden:

Warum sollte ich einen Singleton (zustandslos) erstellen, anstatt statische Methoden zu verwenden?

Warum wird eine Objektinstanz benötigt, wenn ein Objekt keinen Status hat?



Denken Sie nicht, da wir über 2 verschiedene Sprachen sprechen, so dass die Antwort variieren kann, aber danke für den Link, in Java hat der Begriff "Monostat" nie gehört
Sebastien Lorber

Antworten:


79

Oft werden Singletons verwendet, um einer Anwendung einen globalen Status hinzuzufügen. (Um ehrlich zu sein, meistens als wirklich notwendig, aber das ist ein Thema für ein anderes Mal.)

Es gibt jedoch einige Eckfälle, in denen sogar ein zustandsloser Singleton nützlich sein kann:

  • Sie erwarten, es in absehbarer Zeit mit dem Staat zu erweitern.
  • Sie benötigen aus einem bestimmten technischen Grund eine Objektinstanz . Beispiel: Synchronisationsobjekte für die C # - oder die Java- Anweisung.
    locksynchronized
  • Sie benötigen eine Vererbung, dh Sie möchten Ihren Singleton problemlos durch einen anderen ersetzen können, indem Sie dieselbe Schnittstelle, aber eine andere Implementierung verwenden.
    Beispiel: Die Toolkit.getDefaultToolkit()Methode in Java gibt einen Singleton zurück, dessen genauer Typ systemabhängig ist.
  • Sie möchten eine Referenzgleichheit für einen Sentinel-Wert .
    Beispiel: DBNull.Valuein C #.

27
Ich werde mit +1 gehen, obwohl IMHO-Singletons missbraucht werden , um globale Staaten einzuführen. Der Zweck eines Singletons besteht nicht darin, ein Objekt global verfügbar zu machen, sondern zu erzwingen, dass ein Objekt nur einmal instanziiert wird. Globale Objekte sind ein notwendiges Übel. Sofern nicht wirklich erforderlich, sollte man versuchen, sie nicht zu verwenden, da sie im Allgemeinen zu einer hohen Kopplung mit SomeSingleton.getInstance (). SomeMethod () führen. :)
back2dos

Dies kann in Spielen nützlich sein, in denen Sie nur eine Renderinstanz anstelle mehrerer Renderinstanzen möchten, oder in einer Netzwerk-Piping-Klasse, in der Sie einen sicheren Kanal einrichten, bei dem jeweils nur eine Verbindung bestehen kann.
Tschallacka

2
Der Teil "Ersetzen Sie einfach Ihren Singleton" ist aus meiner Sicht der wichtigste Punkt. Rest ist der Implementierung einer statischen Klasse ziemlich nahe.
Teoman Shipahi

1
Singletons sind nützliche Nicht-Null-Sentinel-Werte für Summen- / Produkttypen und ähnliches. Beispiel: Der Wert None / Nothing in einem Optionstyp oder der Wert Empty für einen Auflistungstyp. Als Bonus erhalten Sie schnell keine / leere Tests, da nur die Referenzgleichheit erforderlich ist.
Itsbruce

@itsbruce: Ihre Beispiele sind keine Singletons : Die leere Liste ist nicht die einzig mögliche Instanz der List-Klasse, und der Wert None ist nicht die einzig mögliche Instanz der Option-Klasse. Allerdings gibt es beispielsweise in dem Sentinel - Wert sind Singletons, und ich habe die Freiheit, fügen Sie eine meiner Antwort genommen. Danke für die Eingabe!
Heinzi

37

Ich konnte einen Fall für einen zustandslosen Singleton anstelle einer statischen Methodenklasse sehen, nämlich für Dependency Injection .

Wenn Sie über eine Hilfsklasse von Dienstprogrammfunktionen verfügen, die Sie direkt verwenden, wird eine versteckte Abhängigkeit erstellt. Sie haben keine Kontrolle darüber, wer es wo verwenden kann. Wenn Sie dieselbe Hilfsklasse über eine zustandslose Singleton-Instanz einfügen, können Sie steuern, wo und wie sie verwendet wird, und sie bei Bedarf ersetzen / verspotten / usw.

Wenn Sie es zu einer Singleton-Instanz machen, stellen Sie einfach sicher, dass Sie nicht mehr Objekte des Typs als erforderlich zuweisen (da Sie immer nur eines benötigen).


1
"Sie haben keine Kontrolle darüber, wer es wo verwenden kann." Warum sollte es jemand brauchen?
Hagrawal

1
@ Hagrawal zu Testzwecken, sollten Sie in der Lage sein, es zu verspotten
Jemshit Iskenderov

15

Eigentlich habe ich eine andere Antwort gefunden, die hier nicht erwähnt wird: Statische Methoden sind schwerer zu testen.

Es scheint, dass die meisten Test-Frameworks hervorragend zum Verspotten von Instanzmethoden geeignet sind, aber viele von ihnen behandeln das Verspotten statischer Methoden nicht auf anständige Weise.


2
Aber Powermock scheint dazu in der Lage zu sein
Sebastien Lorber

6

In den meisten Programmiersprachen entziehen sich Klassen einem Großteil des Typsystems. Während eine Klasse mit ihren statischen Methoden und Variablen ein Objekt ist, kann sie sehr oft keine Schnittstelle implementieren oder andere Klassen erweitern. Aus diesem Grund kann es nicht polymorph verwendet werden, da es nicht der Subtyp eines anderen Typs sein kann. Zum Beispiel, wenn Sie eine Schnittstelle IFooable, die von mehreren Verfahren Signaturen anderer Klassen erforderlich ist, das Klassenobjekt StaticFookann nicht anstelle verwendet werden , IFooablewährend, FooSingleton.getInstance()kann (unter der Annahme, FooSingletonGeräten IFooable).

Bitte beachten Sie, dass, wie ich Heinzis Antwort kommentierte, ein Singleton ein Muster zur Steuerung der Instanziierung ist. Sie ersetzt new Class()mit Class.getInstance(), was den Autor gibt Classmehr Kontrolle über Instanzen, die er die Schaffung von unnötigen Instanzen zu verhindern , verwenden kann. Der Singleton ist nur ein ganz besonderer Fall des Fabrikmusters und sollte als solcher behandelt werden. Die allgemeine Verwendung macht es eher zum Sonderfall globaler Register, was oftmals schlecht ist, da globale Register nicht einfach so oder so verwendet werden sollten.

Wenn Sie globale Hilfsfunktionen bereitstellen möchten, funktionieren statische Methoden einwandfrei. Die Klasse fungiert nicht als Klasse, sondern nur als Namespace. Ich schlage vor, Sie bewahren einen hohen Zusammenhalt, oder Sie könnten mit seltsamsten Kopplungsproblemen enden.

greetz
back2dos


4

Es gibt einen Kompromiss zwischen der Verwendung welcher. Singletons können einen Status haben oder nicht und sie beziehen sich auf Objekte. Wenn sie nicht den Status beibehalten und nur für den globalen Zugriff verwendet werden, ist statisch besser, da diese Methoden schneller sind. Wenn Sie jedoch Objekte und OOP-Konzepte (Inheritance Polymorphism) verwenden möchten, ist Singleton besser.

Betrachten Sie ein Beispiel: java.lang.Runtime ist eine Singleton-Klasse in Java. Diese Klasse ermöglicht unterschiedliche Implementierungen für jede JVM. Die Implementierung ist pro JVM einzeln. Wenn diese Klasse statisch gewesen wäre, können wir keine unterschiedlichen Implementierungen basierend auf JVM übergeben.

Ich fand diesen Link wirklich hilfreich: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html ?

Ich hoffe es hilft!!


Diese Antwort ist gut, um ein konkretes Beispiel in die reale Welt aufzunehmen.
Systemovich

2

Für mich "Want Object State Singleton verwenden, Want Function statische Methode verwenden"

Es kommt darauf an, was Sie wollen. Wann immer Sie den Objektzustand wollen (zB Polymorphismus wie Nullzustand stattnull oder Standardstatus), ist Singleton die geeignete Wahl für Sie, während die statische Methode verwendet wird, wenn Sie eine Funktion benötigen (Eingaben empfangen und dann eine Ausgabe zurückgeben).

Ich empfehle für den Singleton-Fall, dass er nach der Instanziierung immer den gleichen Status haben sollte. Es sollte weder klonbar sein noch einen Wert erhalten, in den es gesetzt werden soll (außer statische Konfiguration aus der Datei, z. B. Eigenschaftendatei in Java).

PS Die Leistung zwischen diesen beiden ist in Millisekunden unterschiedlich. Konzentrieren Sie sich also zuerst auf die Architektur .


1

Singleton ist nicht staatenlos, es hält den globalen Zustand.

Einige Gründe, die ich mir vorstellen kann, Singleton zu verwenden, sind:

  • Um Speicherlecks zu vermeiden
  • Bereitstellen des gleichen Status für alle Module in einer Anwendung, z. B. Datenbankverbindung

Ich weiß, aber tatsächlich kann ein Singleton mehr oder weniger staatenlos sein ... Wenn er kein Klassenattribut teilt ...
Sebastien Lorber
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.