Sind unveränderliche / zustandslose Singletons schlecht?

12

In letzter Zeit gab es eine Art Revolution gegen Singletons, aber stimmt etwas nicht mit ihnen, wenn sie staatenlos sind?

Ich kenne die Überbeanspruchung und alles ... das gilt für alles, nicht nur für Singletons.

m3th0dman
quelle
1
Singletons sind im Prinzip nicht schlecht, sie werden einfach massiv überbeansprucht.
Bart van Ingen Schenau
3
was meinst du mit letzter zeit
Manoj R
5
@ Joachim Sauer: Warum müsstest du ersetzen; Wenn es zustandslos ist, können Sie es direkt testen.
m3th0dman
1
Wenn Sie einen Singleton ohne Status haben, dann haben Sie im Grunde genommen eine statische Utility-Klasse, die dazu neigt, sich in das Anti-Pattern der God-Klasse hineinzuentwickeln. Sie können stattdessen in dem Kontext, in dem sie verwendet werden, in der Regel statische Methoden verwenden (oder noch besser: Verwenden Sie Erweiterungsmethoden in C #).
Spoike
1
Mögliches Duplikat von Singleton ohne Staat
Caleth

Antworten:

12
  > Are immutable/stateless singletons bad?
  • Nein, wenn sie nicht von anderen externen Systemen abhängig sind.
    • Beispiel: Eine Stringutility, die HTML in einem String verliert.
    • Grund: Bei Unittests besteht keine Notwendigkeit, dies durch einen Schein / Simulator zu ersetzen.
  • Ja, wenn Ihr unveränderlicher / zustandsloser Singleton von anderen externen Systemen / Diensten abhängt und Sie Unittesting durchführen möchten (isoliertes Testen)
    • Beispiel: Ein Service, der von einem externen Tax-Calculator-Webservice abhängig ist.
    • Grund: Um Unittests mit diesem Dienst (isoliert) durchzuführen, müssen Sie die externen Systeme / Dienste simulieren / verspotten.

Weitere Details finden Sie unter the-onion-architecture


  • Singleton-s kann Unit-Tests (isoliert) erschweren / unmöglich machen und
  • Versteckte Abhängigkeiten / Kopplungen können als Problem angesehen werden, wie von @yBee erklärt

Ich sehe keine anderen Gründe, warum ich Singletons nicht benutze.

k3b
quelle
Sie müssten diesen externen Webdienst immer noch verspotten, wenn Sie Ihre Klasse testen möchten, auch wenn es sich nicht um einen (zustandslosen) Singleton handelt.
m3th0dman
@ m3th0dman Ich stimme zu
k3b
10

Es kommt immer auf die Nutzung an. Ich denke , die Revolution kommt von der Tatsache, dass jeder Programmierer dieses Muster wie lernt das objektorientierte Muster. Die meisten vergessen zu überlegen, wo es Sinn macht und wo nicht.
Dies gilt natürlich für jedes Muster. Nur durch die Verwendung von Mustern erstellen Sie keinen guten Code oder keine gute Software.

Wenn Sie einen Singleton ohne Status haben, warum nicht eine Klasse verwenden, die nur statische Methoden anbietet (oder eine statische Klasse verwenden)?

Hier einige Posts zu globalen Variablen und Singletons im Allgemeinen.

Ich wäre nicht so streng wie der Autor, aber er zeigt, dass man in den meisten Fällen, in denen man denkt, dass man einen Singleton braucht, diesen nicht wirklich braucht.

StampedeXV
quelle
1
Warum nicht eine Klasse mit statischen Methoden verwenden? Vererbung zum Beispiel ...
m3th0dman
3
@ m3th0dman: Klingt nicht nach einem guten Ort für die Vererbung.
Billy ONeal
@BillyONeal Sie können sagen, dass etwas für die Vererbung gut oder schlecht ist, wenn Sie das Domänenmodell kennen, was auf diese Weise modelliert werden soll ...
m3th0dman
2
@ m3th0dman: Ähm, nein. Ich kann ziemlich positiv sein, ohne etwas über das Domain-Modell zu wissen. Vererbung ist für polymorphes Verhalten. Aber als Singleton wirst du kein polymorphes Verhalten haben.
Billy ONeal
1
@ m3th0dman: Da zum Abrufen des Singleton-Objekts der Name des Singleton am Aufrufstandort angegeben werden muss. Das heißt, Sie verwenden kein polymorphes Verhalten. Dies bedeutet, dass die Komposition wesentlich flexibler ist als die Vererbung.
Billy ONeal
7

Es gibt nichts, was ein unveränderlicher zustandsloser Singleton tun kann, was eine statische Klasse nicht kann.

Es gibt einfach keinen Grund, die zusätzliche Komplexitätsebene hinzuzufügen, die -> Instance () erzeugt, während der einfache Aufruf einer statischen Methode klarer, ressourcenschonender und wahrscheinlich schneller sein wird.

Es ist nicht so, dass sie falsch liegen. Es ist so, dass es einen besseren Weg gibt. Es gibt Szenarien, in denen normale ("stateful") Singletons der richtige Weg sind. Das Böse an Singleton ist, dass sie häufig missbraucht werden, mit denselben schlechten Ergebnissen wie globale Variablen, aber es gibt bestimmte Fälle, in denen die Verwendung eines Singletons einfach richtig ist. Für Staatenlose gibt es keine derartigen Fälle.

SF.
quelle
Ich wette, Sie können einige Fälle konstruieren, in denen ein Singleton einige Vorteile hat. Abhängig von Szenario und Programmiersprache möglich (z. B. Ausnutzen von Lazy Loading).
StampedeXV
1
@StampedeXV: Ja, sicherlich ein Stateful Singleton. Ein staatenloser und unveränderlicher - ich wäre sehr gespannt auf Beispiele, aber ich halte nicht den Atem an.
SF.
Ok, du hast einen Punkt. Ich habe Ihre Antwort ein wenig verallgemeinert. Für unveränderliche Staatenlose sehe ich auch keinen Vorteil.
StampedeXV
1
Mit Klassen, die nur statische Funktionen haben, können Sie Vererbung / Polymorphismus nicht verwenden, was eine große Grenze darstellt ...
m3th0dman
1
Es gibt nichts, was ein unveränderlicher zustandsloser Singleton tun kann, was eine statische Klasse nicht kann. Nun, statische Methoden können keine Schnittstelle implementieren, die ein Singleton könnte
Michal M
3

Das Hauptproblem bei Singleton ist, dass es Abhängigkeiten und Kopplungen verbirgt, insbesondere wenn es in einem übergreifenden Szenario verwendet wird. Weitere Informationen finden Sie unter Singletons sind pathologische Lügner oder Warum Singletons böse sind .

Auf der anderen Seite kann ein Zustand ohne Singleton hilfreich sein und die Leistung verbessern, wenn er nicht missbraucht wird. Betrachten Sie ein Beispiel:

interface Interface
{
    void Method();
}

class StatelessSingleton : Interface
{
    public static readonly StatelessSingleton Instance = new StatelessSingleton();
    private StatelessSingleton() { }

    public void Method() { }
}

class User
{
    public User(Interface i) { /* ... */ }
}

Hier fungiert der StatelessSingleton als Standardimplementierung der Schnittstelle und wird in den User-Konstruktor eingefügt. Es gibt keine fest codierte Kopplung und keine erweiterten Abhängigkeiten. Eine statische Klasse kann aufgrund der zugrunde liegenden Schnittstelle nicht verwendet werden, es gibt jedoch keinen Grund, mehr als eine Instanz eines Standards zu erstellen. Aus diesem Grund scheint ein Singleton ohne Status eine geeignete Wahl zu sein.

Vielleicht sollten wir jedoch ein anderes Muster für eine Standardimplementierung verwenden:

class Implementation : Interface
{
    private readonly Action _method;

    public Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

Es beeinträchtigt die Leistung in Bezug auf StatelessSingleton, stellt jedoch eine generische Implementierung der Schnittstelle dar. Eine ähnliche Lösung wird von der IProgress- Schnittstelle verwendet.

Aber warum sollte es möglich sein, mehr als eine Implementierung des Standardverhaltens zu erstellen? Trotzdem können wir beides kombinieren:

class Implementation : Interface
{
    public readonly Implementation Default = new Implementation();

    private readonly Action _method;

    private Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

Zusammenfassend glaube ich, dass es Orte gibt (wie in den Standardeinstellungen dargestellt), an denen Singletons nützlich sind. Die Hauptdefinition von Singleton besagt, dass nicht mehr als eine Instanz einer Klasse erstellt werden darf . Es ist wie Atomkraft. Kann eine Energie oder eine Bombe produzieren. Es hängt vom Menschen ab.

yBee
quelle