Unterschied zwischen statischer Klasse und Singleton-Muster?


1768

Welcher reale (dh praktische) Unterschied besteht zwischen einer statischen Klasse und einem Singleton-Muster?

Beide können ohne Instanziierung aufgerufen werden, beide stellen nur eine "Instanz" bereit und keine von ihnen ist threadsicher. Gibt es noch einen anderen Unterschied?


4
Abhängig von der Sprachimplementierung und Ihren Verwendungsmustern ist ein Singleton möglicherweise weniger effizient, da die getInstance()Methode jedes Mal aufgerufen werden muss, wenn Sie sie verwenden möchten (obwohl dies in den meisten Fällen wahrscheinlich keine Rolle spielt ).
zu viel PHP

5
Es gibt bereits viele Antworten. Es ist eigentlich ein singletonObjekt, bei dem staticMethoden nur Funktionen sind, eine Nicht-OO-Entität.
Fastcodejava

4
Hängt von der Implementierung ab. Csharpindepth.com/Articles/General/Singleton.aspx
VJAI

4
Es gibt einen Unterschied, wenn Sie Dritten erlauben möchten, die Implementierung der Klasse bereitzustellen. In diesem Fall benötigen Sie normalerweise auch ein Factory-Muster. Siehe agiletribe.wordpress.com/2013/10/08/…
AgilePro

IMO diese Antwort fasst es sehr gut zusammen stackoverflow.com/questions/14097656/…
Dave

Antworten:


1251

Was lässt Sie sagen, dass entweder eine Singleton- oder eine statische Methode nicht threadsicher ist? Normalerweise sollten beide implementiert werden, um threadsicher zu sein.

Der große Unterschied zwischen einem Singleton und einer Reihe statischer Methoden besteht darin, dass Singletons Schnittstellen implementieren können (oder von nützlichen Basisklassen abgeleitet sind, obwohl dies meiner Erfahrung nach weniger häufig ist), sodass Sie den Singleton so weitergeben können, als wäre es "nur eine andere" " Implementierung.


29
Nun, wenn Sie es vorziehen, ist auch keiner von ihnen threadsicher, Sie müssen sie threadsicher machen, beide, also kein Unterschied.
Jorge Córdoba

119
Können Sie ein Beispiel geben von etwas, das ist von Natur aus THREAD, andere als unveränderliche Typen?
Jon Skeet

26
Zu Skeet: Leute, die sagen, dass Singleton nicht threadsicher ist, bedeuten, dass ein Singleton unnötigerweise ständig zwischen Threads geteilt wird, während Stapelobjekte bei Bedarf gemeinsam genutzt werden, was bedeutet, dass Sie keine unnötige Synchronisation durchführen müssen.

45
@Geek: Stellen Sie sich vor, der Singleton implementiert eine Schnittstelle Foound Sie haben eine Methode, die a Fooals Parameter verwendet. Mit diesem Setup können Anrufer den Singleton als Implementierung verwenden - oder sie können eine andere Implementierung verwenden. Die Methode ist vom Singleton entkoppelt. Vergleichen Sie dies mit der Situation, in der die Klasse nur statische Methoden hat - jeder Code, der diese Methoden aufrufen möchte, ist eng mit der Klasse verbunden, da angegeben werden muss, welche Klasse die statischen Methoden enthält.
Jon Skeet

10
@AmirBareket: Es ist jedoch kein Singleton gemäß dem Singleton-Entwurfsmuster. Wenn die Klasse selbst das Erstellen mehrerer Instanzen zulässt, handelt es sich nicht um eine Singleton-IMO, unabhängig davon, was die Factory tut.
Jon Skeet

476

Die wahre Antwort stammt von Jon Skeet in einem anderen Forum hier .

Ein Singleton ermöglicht den Zugriff auf eine einzelne erstellte Instanz. Diese Instanz (oder vielmehr ein Verweis auf diese Instanz) kann als Parameter an andere Methoden übergeben und als normales Objekt behandelt werden.

Eine statische Klasse erlaubt nur statische Methoden.


64
Warum sollten Sie jedoch einen Singleton als Parameter übergeben, wenn Sie von nahezu jedem Ort aus auf dieselbe Instanz zugreifen können, indem Sie die statische Methode getInstance () aufrufen?
Henrique Ordine

23
@HenriqueOrdine Kann es also in vorhandenen Code passen und eine Schnittstelle bereitstellen?

6
@HenriqueOrdine Sie sprechen von einer statischen Klasse, nicht von einer Klasse mit statischen Methoden. Statische Klasse kann nicht instanziiert werden. Wenn Sie jedoch eine Instanz einer (nicht statischen) Klasse übergeben, die statische Methoden enthält, können Sie keine statischen Methoden für eine Instanz aufrufen.
Goran

3
Was ist eine statische Klasse? Zumindest in Java gibt es so etwas nicht.
Henrique Ordine

16
@Goran Ich war anfangs sehr verwirrt von Ihrer Formulierung. Sie sagten "Sie können keine statischen Methoden für eine Instanz aufrufen". Ich las das als "Wenn Sie einen Verweis auf ein instanziiertes Objekt haben, können Sie keine statischen Methoden aufrufen, die es möglicherweise hat." Das ist natürlich falsch. Nachdem Sie es einige Male noch einmal gelesen haben, haben Sie gemeint, dass Sie "innerhalb statischer Methoden nicht auf nicht statische Objekte in der Klasse zugreifen können", was richtig ist. Möchten Sie dies für alle klarstellen, die mit diesen Konzepten noch nicht vertraut sind und auf diese Antwort stoßen und Ihre Kommentare lesen.
Andrew Steitz

359
  1. Singleton-Objekte werden im Heap gespeichert , statische Objekte jedoch im Stapel .
  2. Wir können das Singleton-Objekt klonen (wenn der Designer es nicht verboten hat), aber wir können das statische Klassenobjekt nicht klonen.
  3. Singleton-Klassen folgen dem OOP (Object Oriented Principles), statische Klassen nicht.
  4. Wir können eine interfacemit einer Singleton-Klasse implementieren , die statischen Methoden einer Klasse (oder z. B. ein C # static class) jedoch nicht.

99
Die zweite Aussage ist falsch. Wir können kein Singleton-Objekt klonen. Die Singleton-Implementierung muss dies ablehnen. Wenn Sie Singleton wirklich klonen können, ist es nicht Singleton.
Alexander Yancharuk

19
Diese Antwort ist für Java nicht korrekt: Weder der Singleton noch der Static verwenden den Stack.
AgilePro

72
# 1 ist nicht wichtig. # 2 beschreibt eine fehlerhafte Implementierung. # 3 ist völlig ungerechtfertigt.
Casey

31
Wie kann ein statisches Objekt im Stapel gespeichert werden? Ein neuer Stapelrahmen wird erstellt, wenn Sie eine Methode aufrufen. Er speichert die lokalen Variablen der Methode, dieser Stapelrahmen wird entfernt, wenn die Methode zurückgegeben wird, und diese lokalen Variablen gehen verloren. Sicher, der Stapel ist schnell, aber nicht zum Speichern statischer Objekte geeignet.
Mike_m

23
Ich kann die Anzahl der Upvotes zu diesem Thema nicht verstehen. 1) Warum sollte Singleton im Stapel gespeichert werden müssen? In verwalteten Sprachen wie C # oder Java werden Daten in einem verwalteten Heap gespeichert, mit Ausnahme lokaler Methodenvariablen / -parameter. 2) Wenn Sie es klonen können, ist es kein ordnungsgemäß implementierter Singleton. 3) Singleton ist als OOP-Anti-Pattern bekannt; dh etwas, das Sie nach Möglichkeit vermeiden sollten. 4) Dies ist das einzige, was richtig ist.
Groo

152

Das Singleton-Muster bietet gegenüber statischen Klassen mehrere Vorteile. Erstens kann ein Singleton Klassen erweitern und Schnittstellen implementieren, während eine statische Klasse dies nicht kann (er kann Klassen erweitern, erbt jedoch nicht ihre Instanzmitglieder). Ein Singleton kann träge oder asynchron initialisiert werden, während eine statische Klasse im Allgemeinen beim ersten Laden initialisiert wird, was zu potenziellen Problemen beim Laden von Klassen führt. Der wichtigste Vorteil ist jedoch, dass Singletons polymorph behandelt werden können, ohne dass ihre Benutzer davon ausgehen müssen, dass es nur eine Instanz gibt.


10
+1 für gute, pragmatische Punkte. Singleton-Muster werden im Allgemeinen überbeansprucht, aber es gibt einige Situationen, in denen es passt. Siehe auch: agiletribe.wordpress.com/2013/10/08/…
AgilePro

3
Sie haben Recht mit dem Vorteil, polymorph zu sein. Dies ist der wichtigste Punkt
Ahmad

Verschachtelte statische Klasse kann Schnittstelle implementieren. Versuchen Sie es zu codieren, wird funktionieren. Ich konnte den Code ohne Fehler kompilieren.
Nanosoft

75

staticKlassen sind nicht für irgendetwas, das Staat braucht. Es ist nützlich, um eine Reihe von Funktionen zusammenzustellen, z. B. Math(oder Utilsin Projekten). Der Klassenname gibt uns also nur einen Hinweis, wo wir die Funktionen finden können und nichts weiter.

Singletonist mein Lieblingsmuster und ich verwende es, um etwas an einem einzigen Punkt zu verwalten. Es ist flexibler als staticKlassen und kann seinen Zustand beibehalten. Es kann Schnittstellen implementieren, von anderen Klassen erben und die Vererbung zulassen.

Meine Regel für die Wahl zwischen staticund singleton:

Wenn es eine Reihe von Funktionen gibt, die zusammengehalten werden sollten, staticist dies die Wahl. Alles andere, das einmaligen Zugriff auf einige Ressourcen benötigt, könnte als implementiert werden singleton.


16
Warum sollten statische Klassen nichts tun, was zum Speichern des Status erforderlich ist?
Trisped

12
@Trisped: Sie haben weder eine genaue Kontrolle über die Initialisierung noch über die Finalisierung.
Xaqron

7
Du hast mich bei "Singleton ist mein Lieblingsmuster" verloren. Singleton ist eine so scharfe Ecke, dass es sowohl als Anti-Muster als auch als Muster betrachtet werden sollte. Klassen können durchaus statische Zustände haben, das ist auch Einzelzugriff, wenn ein statischer Zustand mehr "Einzelzugriff" als Singletons ist, da die meisten Singleton-Implementierungen fehlerhaft sind, d. H. Sie können den Singleton klonen, während statisch durch die Definition als eindeutig gesegnet wird.
PoweredByRice

1
Was bedeutet es, den Zustand aufrechtzuerhalten? Was ist Staat?
Kyle Delaney

2
@KyleDelaney: Einfach Stateist die Kombination verschiedener Eigenschaften eines Objekts, die sich normalerweise im Laufe der Zeit ändern. Sie können Google für die formale Definition.
Xaqron

65

Statische Klasse: -

  1. Sie können die Instanz der statischen Klasse nicht erstellen.

  2. Wird automatisch von der .NET Framework Common Language Runtime (CLR) geladen, wenn das Programm oder der Namespace mit der Klasse geladen wird.

  3. Statische Klasse kann keinen Konstruktor haben.

  4. Wir können die statische Klasse nicht an method übergeben.

  5. Wir können die statische Klasse nicht an eine andere statische Klasse in C # erben.

  6. Eine Klasse mit allen statischen Methoden.

  7. Bessere Leistung (statische Methoden werden bei der Kompilierung gebunden)

Singleton: -

  1. Sie können eine Instanz des Objekts erstellen und wiederverwenden.

  2. Die Singleton-Instanz wird zum ersten Mal erstellt, wenn der Benutzer dies anfordert.

  3. Die Singleton-Klasse kann einen Konstruktor haben.

  4. Sie können das Objekt der Singleton-Klasse erstellen und an die Methode übergeben.

  5. Die Singleton-Klasse sagt keine Einschränkung der Vererbung aus.

  6. Wir können die Objekte einer Singleton-Klasse, aber nicht einer statischen Klasse entsorgen.

  7. Methoden können überschrieben werden.

  8. Kann bei Bedarf verzögert geladen werden (statische Klassen werden immer geladen).

  9. Wir können eine Schnittstelle implementieren (statische Klasse kann keine Schnittstelle implementieren).


13
Statische Klassen haben Konstruktoren: msdn.microsoft.com/en-us/library/k9x6w0hc.aspx
Tomer Arazy

2
Ja, static kann einen Konstruktor haben, der für diese Klasse intern ist. Dies wird aufgerufen, wenn eine statische Methode in der Klasse aufgerufen wird.
Rahulmr

Für Singleton zur Kompilierungszeit wird es im HEAP-Speicher gespeichert. Wenn es jedoch einmal instanziiert wird, wird es in STACK gespeichert?
Luminous_Dev

@Luminous_Dev Nein. Jede Singleton-Instanz ist am Ende des Tages eine Objektinstanz. Es wird ohne Zweifel auf einem Haufen gespeichert.
RBT

1
@rahulmr Wichtiger Unterschied: Der Konstruktor wird auch aufgerufen, bevor die erste (nur AKA) Instanz erstellt wird.
CoolOppo

53

Eine statische Klasse hat nur statische Methoden, für die ein besseres Wort "Funktionen" wäre. Der in einer statischen Klasse verkörperte Designstil ist rein prozedural.

Singleton hingegen ist ein Muster, das für das OO-Design spezifisch ist. Es handelt sich um eine Instanz eines Objekts (mit allen damit verbundenen Möglichkeiten, wie z. B. Polymorphismus), mit einem Erstellungsverfahren, das sicherstellt, dass es während seiner gesamten Lebensdauer immer nur eine Instanz dieser bestimmten Rolle gibt.


1
Polymorphismus kommt bei Singletons überhaupt nicht ins Spiel

32
Also denkst du. Ich denke anders. ;) Stellen Sie sich zum Beispiel eine Singleton-Factory vor, die eine Schnittstelle zurückgibt. Sie wissen, dass Sie einen ISingleton erhalten (und dieser ist für immer derselbe), aber nicht unbedingt welche Implementierung.
Morendil

Verschachtelte statische Klassen können auch Instanzmethoden haben. Sie sind nicht nur auf statische Methoden beschränkt. Codieren Sie sie und Sie können sehen.
Nanosoft

In Sprachen mit einem schöneren Objektmodell (z. B. Ruby) sind Klassen auch Objekte. Der "rein prozedurale" Aspekt einer statischen Klasse ist eine willkürliche Einschränkung, die von der Sprache auferlegt wird.
Max

36

Im Singleton-Muster können Sie den Singleton als Instanz eines abgeleiteten Typs erstellen. Dies ist mit einer statischen Klasse nicht möglich.

Kurzes Beispiel:

if( useD3D )
    IRenderer::instance = new D3DRenderer
else
    IRenderer::instance = new OpenGLRenderer

39
Es ist nicht wirklich ein Singleton-Muster, sieht für mich eher wie eine Fabrik aus.
Vava

10
Nicht wirklich, der grundlegende Unterschied zwischen den beiden besteht darin, dass der Singleton sein einzelnes Objekt "zwischenspeichert" und immer wieder dasselbe zurückgibt (einen Verweis darauf). Das Factory-Muster erstellt neue Instanzen.
Mystic

12
Dann ist es Proxy-Singleton :)
Vava

3
Hmm, ich kenne diese Sorte des Singleton als MonoState.
Huppie

Beispiel ist Fabrikmuster
Rajavel D

26

Um Jon Skeets Antwort zu erweitern

Der große Unterschied zwischen einem Singleton und einer Reihe statischer Methoden besteht darin, dass Singletons Schnittstellen implementieren können (oder von nützlichen Basisklassen abgeleitet sind, obwohl dies weniger häufig im IME vorkommt), sodass Sie den Singleton so weitergeben können, als wäre es "nur eine andere" Implementierung.

Singletons sind einfacher zu bearbeiten, wenn eine Klasse getestet wird. Überall dort, wo Sie Singletons als Parameter übergeben (Konstruktoren, Setter oder Methoden), können Sie stattdessen eine verspottete oder gestoppelte Version des Singletons ersetzen.


Ich glaube nicht, dass man einen Singleton direkt verspotten kann. Müssten Sie nicht eine Schnittstelle deklarieren, die sowohl der Singleton als auch die Mock-Klasse implementieren?
Ellen Spertus

@espertus Warum kannst du deinen Singleton nicht verspotten? Beispiel mit Mockito MySingleton mockOfMySingleton = mock(MySingleton.class).
Mike Rylander

Sie haben Recht, Sie können es mit Tools wie Mockito verspotten, die Reflexion verwenden. Ich meinte, dass Sie es nicht direkt verspotten können, indem Sie es unterordnen und seine Methoden überschreiben.
Ellen Spertus

@espertus Warum nicht? Wenn Sie das zu testende Objekt instanziieren, können Sie die Unterklassenimplementierung Ihres Singletons überall dort ersetzen, wo Sie das Original verwendet hätten. Beispiel:new ClazzToTest(mockSingleton);
Mike Rylander

Ich habe Mockito nicht verwendet, aber wie können Sie eine Klasse mit einem privaten Konstruktor unterordnen, was bei Singletons der Fall ist, außer durch Reflektion? Verwandte Diskussionen: stackoverflow.com/questions/2302179/mocking-a-singleton-class stackoverflow.com/questions/15939023/…
Ellen Spertus

23

Hier ist ein guter Artikel: http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

Statische Klassen

  • eine Klasse mit allen statischen Methoden .
  • bessere Leistung (statische Methoden werden bei der Kompilierung gebunden)
  • Methoden können nicht überschrieben werden, aber Methoden können ausgeblendet werden. ( Was versteckt eine Methode in Java? Selbst die JavaDoc-Erklärung ist verwirrend. )

    public class Animal {
        public static void foo() {
            System.out.println("Animal");
        }
    }
    
    public class Cat extends Animal {
        public static void foo() {  // hides Animal.foo()
            System.out.println("Cat");
        }
    }
    

Singleton

Zusammenfassend würde ich nur statische Klassen verwenden, um util-Methoden zu halten, und Singleton für alles andere.


Bearbeitungen


4
Ich weiß nichts über Java, aber in .Net sind Ihre letzten beiden Punkte falsch. Statische Klassen können auf statische Eigenschaften und Felder verweisen, sodass sie im Status gleich sind. Und sie werden faul geladen - der statische Konstruktor wird ausgeführt, wenn: 1) eine Instanz der Klasse erstellt wird. 2) Auf alle statischen Mitglieder der Klasse wird verwiesen. 1 gilt nicht, wodurch 2 übrig bleibt. Eine statische Klasse wird also erst geladen, wenn sie zum ersten Mal verwendet wird.
Jmoreno

1
Für statische Klassen können Sie die statische Methode zwar nicht überschreiben, aber vor der übergeordneten Methode ausblenden.
Max Peng

wenn Animal animal = new Cat();dann animal.foo();was passiert
Luminous_Dev

@jmoreno statische Klasse wird erst bei der ersten Verwendung geladen? Ich glaube, es wird zur Kompilierungszeit im Stapelspeicher gespeichert. Und es wird sofort zugegriffen, nicht wahr?
Luminous_Dev

@Luminous_Dev: Zumindest für .net verfügt eine statische Klasse über einen Konstruktor, der beim ersten Zugriff ausgeführt wird. Nein, auf ihn kann nicht sofort zugegriffen werden. Der statische Konstruktor könnte theoretisch eine unbegrenzte Zeit in Anspruch nehmen. Wo es (oder eine andere Klasse gespeichert ist) ist ein Implementierungsdetail, das für diese Frage nicht wirklich relevant ist.
jmoreno

22

Ein weiterer Vorteil eines Singletons besteht darin, dass er leicht serialisiert werden kann. Dies kann erforderlich sein, wenn Sie seinen Status auf einer Disc speichern oder an einen anderen Ort senden müssen.


19

Ich bin kein großartiger OO-Theoretiker, aber nach meinem Wissen ist das einzige OO-Merkmal, das statischen Klassen im Vergleich zu Singletons fehlt, der Polymorphismus. Aber wenn Sie es nicht brauchen, können Sie mit einer statischen Klasse natürlich Vererbung (nicht sicher über die Schnittstellenimplementierung) und Daten- und Funktionskapselung haben.

Der Kommentar von Morendil: "Der in einer statischen Klasse verkörperte Designstil ist rein prozedural." Ich kann mich irren, aber ich bin anderer Meinung. In statischen Methoden können Sie auf statische Elemente zugreifen. Dies entspricht genau den Singleton-Methoden, die auf ihre einzelnen Instanzmitglieder zugreifen.

edit:
Ich denke jetzt tatsächlich, dass ein weiterer Unterschied darin besteht, dass eine statische Klasse beim Programmstart * instanziiert wird und während der gesamten Lebensdauer des Programms lebt, während ein Singleton irgendwann explizit instanziiert wird und auch zerstört werden kann.

* oder es kann beim ersten Gebrauch instanziiert werden, abhängig von der Sprache, denke ich.


15
Ja, alle anderen scheinen die Tatsache zu ignorieren, dass eine Klasse mit statischen Methoden auch private statische Felder haben kann, mit denen sie den Status beibehalten kann (und einige davon über öffentliche statische Setter / Getter dem Client-Code aussetzen kann).
user289463

17

Um Jons Punkt zu veranschaulichen, kann das, was unten gezeigt wird, nicht ausgeführt werden, wenn Logger eine statische Klasse war. Die Klasse SomeClasserwartet, dass eine Instanz der ILoggerImplementierung an ihren Konstruktor übergeben wird.

Die Singleton-Klasse ist wichtig, damit die Abhängigkeitsinjektion möglich ist.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            var someClass = new SomeClass(Logger.GetLogger());
        }


    }

    public class SomeClass 
    {
        public SomeClass(ILogger MyLogger)
        {

        }
    }

    public class Logger : ILogger
    {
        private static Logger _logger;
        private Logger() { }

        public static Logger GetLogger()
        {
            if (_logger==null)
            {
                _logger = new Logger();
            }

            return _logger;
        }

        public void Log()
        {

        }

    }


    public interface ILogger
    {
         void Log();
    }
}

13

Nun, ein Singleton ist nur eine normale Klasse, die instanziiert wird, aber nur einmal und indirekt aus dem Client-Code. Statische Klasse wird nicht instanziiert. Soweit ich weiß, sind statische Methoden (statische Klassen müssen statische Methoden haben) schneller als nicht statische.

Bearbeiten:
Beschreibung der FxCop-Leistungsregel: "Methoden, die nicht auf Instanzdaten zugreifen oder Instanzmethoden aufrufen, können als statisch markiert werden (in VB freigegeben). Danach sendet der Compiler nicht virtuelle Aufrufseiten an diese Mitglieder, wodurch a verhindert wird Überprüfen Sie zur Laufzeit für jeden Aufruf, der sicherstellt, dass der aktuelle Objektzeiger nicht null ist. Dies kann zu einem messbaren Leistungsgewinn für leistungsabhängigen Code führen. In einigen Fällen stellt der Fehler beim Zugriff auf die aktuelle Objektinstanz ein Korrektheitsproblem dar. "
Ich weiß eigentlich nicht, ob dies auch für statische Methoden in statischen Klassen gilt.


11

Singletons werden instanziiert, es gibt nur eine Instanz, die jemals instanziiert wurde, daher die Single in Singleton.

Eine statische Klasse kann nur durch sich selbst instanziiert werden.


Statische Klassen können in Java sehr stark instanziiert werden. Lesen Sie docs.oracle.com/javase/tutorial/java/javaOO/nested.html. Siehe
nanosoft

8

Hauptunterschiede sind:

  • Singleton hat eine Instanz / ein Objekt, während die statische Klasse eine Reihe statischer Methoden ist
  • Singleton kann zB über eine Schnittstelle erweitert werden, statische Klassen hingegen nicht.
  • Singleton kann vererbt werden, was Open / Close-Prinzipien in SOLID-Prinzipien unterstützt. Andererseits kann statische Klasse nicht vererbt werden, und wir müssen Änderungen an sich selbst vornehmen.
  • Singleton-Objekte können an Methoden übergeben werden, während statische Klassen, die keine Instanz haben, nicht als Parameter übergeben werden können

7

Singleton ist aus Testsicht ein besserer Ansatz. Im Gegensatz zu statischen Klassen kann Singleton Schnittstellen implementieren, und Sie können eine Scheininstanz verwenden und diese einfügen.

Im folgenden Beispiel werde ich dies veranschaulichen. Angenommen, Sie haben eine Methode isGoodPrice (), die eine Methode getPrice () verwendet, und Sie implementieren getPrice () als Methode in einem Singleton.

Singleton mit getPrice-Funktionalität:

public class SupportedVersionSingelton {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        // calculate price logic here
        return 0;
    }
}

Verwendung von getPrice:

public class Advisor {

    public boolean isGoodDeal(){

        boolean isGoodDeal = false;
        ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
        int price = supportedVersion.getPrice();

        // logic to determine if price is a good deal.
        if(price < 5){
            isGoodDeal = true;
        }

        return isGoodDeal;
    }
}


In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it. 



  public interface ICalculator {
        int getPrice();
    }

Endgültige Singleton-Implementierung:

public class SupportedVersionSingelton implements ICalculator {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        return 0;
    }

    // for testing purpose
    public static void setInstance(ICalculator mockObject){
        if(instance != null ){
instance = mockObject;
    }

Testklasse:

public class TestCalculation {

    class SupportedVersionDouble implements ICalculator{
        @Override
        public int getPrice() { 
            return 1;
        }   
    }
    @Before
    public void setUp() throws Exception {
        ICalculator supportedVersionDouble = new SupportedVersionDouble();
        SupportedVersionSingelton.setInstance(supportedVersionDouble);

    }

    @Test
    public void test() {
          Advisor advidor = new Advisor();
          boolean isGoodDeal = advidor.isGoodDeal();
          Assert.assertEquals(isGoodDeal, true);

    }

}

Wenn wir die Alternative der Verwendung einer statischen Methode zur Implementierung von getPrice () wählen, war es schwierig, getPrice () zu verspotten. Sie könnten statisch mit Power-Mock verspotten, aber nicht alle Produkte könnten es verwenden.


1
Das ist jetzt nicht threadsicher und im Allgemeinen unangenehm in Bezug auf den Zugriff auf die Schnittstellenimplementierung. Sicher, eine Schnittstelle ist gut für die Testbarkeit - aber warum sollte man sich dann mit einem Singleton beschäftigen? Vermeiden Sie es einfach, überhaupt einen Singleton zu haben. Lassen Sie eine Klasse es für Produktionszwecke implementieren, eine Implementierung für Testzwecke, und fügen Sie die richtige Instanz ein, je nachdem, was Sie tun. Der Singleton muss überhaupt nicht mit seinen Anrufern gekoppelt werden.
Jon Skeet

Danke für die Rückmeldung. Es ist sehr einfach, es threadsicher zu machen. Außerdem benutze ich Singleton für Caching-Zwecke.
Amir Bareket

1
Ja, obwohl mit sinnlosem Aufwand. Auch hier ist es einfacher, keinen Singleton zu verwenden.
Jon Skeet

6

Ich stimme dieser Definition zu:

Das Wort " einzeln " bedeutet ein einzelnes Objekt über den gesamten Anwendungslebenszyklus, sodass sich der Bereich auf Anwendungsebene befindet.

Die Statik hat keinen Objektzeiger, daher befindet sich der Bereich auf der Ebene der App-Domäne.

Darüber hinaus sollten beide threadsicher implementiert werden.

Sie können interessante andere Unterschiede finden über: Singleton Pattern Versus Static Class


5

Ein bemerkenswerter Unterschied ist die unterschiedliche Instanziierung, die mit Singletons einhergeht.

Bei statischen Klassen wird es von der CLR erstellt und wir haben keine Kontrolle darüber. Bei Singletons wird das Objekt bei der ersten Instanz instanziiert, auf die zugegriffen werden soll.


4

In vielen Fällen haben diese beiden keinen praktischen Unterschied, insbesondere wenn sich die Singleton-Instanz nie oder nur sehr langsam ändert, z. B. wenn Konfigurationen gehalten werden.

Ich würde sagen, der größte Unterschied ist, dass ein Singleton immer noch eine normale Java Bean ist, im Gegensatz zu einer speziellen statischen Java-Klasse. Aus diesem Grund wird ein Singleton in vielen weiteren Situationen akzeptiert. Dies ist in der Tat die Standard-Instanziierungsstrategie von Spring Framework. Der Verbraucher kann oder kann nicht wissen, dass es sich um einen Singleton handelt, der herumgereicht wird. Er behandelt ihn einfach wie eine normale Java-Bean. Wenn sich die Anforderungen ändern und ein Singleton stattdessen zum Prototyp werden muss, wie wir oft im Frühjahr sehen, kann dies völlig nahtlos erfolgen, ohne dass eine Codezeile für den Verbraucher geändert werden muss.

Jemand anderes hat zuvor erwähnt, dass eine statische Klasse rein prozedural sein sollte, z. B. java.lang.Math. Meiner Meinung nach sollte eine solche Klasse niemals herumgereicht werden und niemals etwas anderes als statisches Finale als Attribute enthalten. Verwenden Sie für alles andere einen Singleton, da dieser viel flexibler und einfacher zu warten ist.


4

Wir haben unser DB-Framework, das Verbindungen zum Back-End herstellt. Um fehlerhafte Lesevorgänge zwischen mehreren Benutzern zu vermeiden, haben wir Singleton-Muster verwendet, um sicherzustellen, dass zu jedem Zeitpunkt eine einzelne Instanz verfügbar ist.

In c # kann eine statische Klasse keine Schnittstelle implementieren. Wenn eine einzelne Instanzklasse eine Schnittstelle für Geschäftsverträge oder IoC-Zwecke implementieren muss, verwende ich hier das Singleton-Muster ohne statische Klasse

Singleton bietet eine Möglichkeit, den Status in zustandslosen Szenarien beizubehalten

Hoffe das hilft dir ..


3
  1. Faules Laden
  2. Unterstützung von Schnittstellen, so dass eine separate Implementierung bereitgestellt werden kann
  3. Möglichkeit, abgeleiteten Typ zurückzugeben (als Kombination aus Lazyloading und Schnittstellenimplementierung)

Verschachtelte statische Klassen können Schnittstellen in Java sehr gut implementieren. Ihr zweiter Punkt ist falsch.
Nanosoft

3

ein. Serialisierung - Statische Mitglieder gehören zur Klasse und können daher nicht serialisiert werden.

b. Obwohl wir den Konstruktor privat gemacht haben, werden statische Elementvariablen weiterhin in die Unterklasse übertragen.

c. Wir können keine verzögerte Initialisierung durchführen, da alles nur beim Laden der Klasse geladen wird.


3

Aus Client-Sicht ist dem Client statisches Verhalten bekannt, das Singleton-Verhalten kann jedoch vor einem Client verborgen abgeschlossen werden. Der Kunde wird möglicherweise nie erfahren, dass es nur eine einzige Instanz gibt, mit der er immer wieder herumspielt.


3

Ich habe folgendes gelesen und denke, dass es auch Sinn macht:

Sich um das Geschäft kümmern

Denken Sie daran, eine der wichtigsten OO-Regeln ist, dass ein Objekt für sich selbst verantwortlich ist. Dies bedeutet, dass Probleme bezüglich des Lebenszyklus einer Klasse in der Klasse behandelt und nicht an Sprachkonstrukte wie statisch usw. delegiert werden sollten.

aus dem Buch Objected-Oriented Thought Process 4th Ed.


Ich würde dem nicht zustimmen, da dies der Klasse wirklich nur eine Verantwortung hinzufügt, was (vorausgesetzt, es tut irgendetwas) bedeutet, dass es jetzt gegen das Prinzip der Einzelverantwortung verstößt.
Schmied

3

In einem Artikel, den ich geschrieben habe, habe ich meinen Standpunkt beschrieben, warum der Singleton viel besser ist als eine statische Klasse:

  1. Statische Klasse ist eigentlich keine kanonische Klasse - es ist ein Namespace mit Funktionen und Variablen
  2. Die Verwendung einer statischen Klasse ist keine gute Vorgehensweise, da objektorientierte Programmierprinzipien verletzt werden
  3. Statische Klasse kann nicht als Parameter für andere übergeben werden
  4. Die statische Klasse eignet sich nicht für die "verzögerte" Initialisierung
  5. Die Initialisierung und Verwendung der statischen Klasse wird immer hart verfolgt
  6. Die Implementierung der Thread-Verwaltung ist schwierig

Ich würde es für die englische Grammatik auffrischen, aber ansonsten ist es eine interessante Lektüre :)
Noctis

3
  1. Wir können das Objekt der Singleton-Klasse erstellen und an die Methode übergeben.

  2. Die Singleton-Klasse unterliegt keiner Einschränkung der Vererbung.

  3. Wir können die Objekte einer statischen Klasse nicht entsorgen, sondern eine Singleton-Klasse.


Was nützt es, einen Singleton an eine Methode zu übergeben, wenn es immer nur einen gibt und dieser immer eine statische Referenz hat?
Aaron Franke

3

Unterscheidung von der statischen Klasse

JDK enthält Beispiele für Singleton und Static. Einerseits java.lang.Mathhandelt es sich um eine letzte Klasse mit statischen Methoden, andererseits java.lang.Runtimeum eine Singleton-Klasse.

Vorteile von Singleton

  • Wenn Sie den Status als Singleton-Muster beibehalten müssen, ist dies die bessere Wahl als die statische Klasse, da das Beibehalten des Status in der statischen Klasse zu Fehlern führt, insbesondere in einer gleichzeitigen Umgebung, die zu Race-Bedingungen führen können, ohne dass eine parallele Synchronisierung durch mehrere Threads erfolgt.

  • Die Singleton-Klasse kann faul geladen werden, wenn es sich um ein schweres Objekt handelt, aber die statische Klasse hat keine solchen Vorteile und wird immer eifrig geladen.

  • Mit Singleton können Sie Vererbung und Polymorphismus verwenden, um eine Basisklasse zu erweitern, eine Schnittstelle zu implementieren und verschiedene Implementierungen bereitzustellen.

  • Da statische Methoden in Java nicht überschrieben werden können, führen sie zu Inflexibilität. Auf der anderen Seite können Sie in der Singleton-Klasse definierte Methoden überschreiben, indem Sie sie erweitern.

Nachteile der statischen Klasse

  • Es ist einfacher, einen Komponententest für Singleton als eine statische Klasse zu schreiben, da Sie ein Scheinobjekt übergeben können, wenn Singleton erwartet wird.

Vorteile der statischen Klasse

  • Die statische Klasse bietet eine bessere Leistung als Singleton, da statische Methoden bei der Kompilierung miteinander verbunden sind.

Es gibt mehrere Realisierungen von Singleton-Mustern mit jeweils Vor- und Nachteilen.

  • Eifriges Laden von Singleton
  • Doppelter Sperr-Singleton
  • Initialisierung-on-Demand-Inhabersprache
  • Der auf Enum basierende Singleton

Detaillierte Beschreibung Jeder von ihnen ist zu ausführlich, deshalb habe ich nur einen Link zu einem guten Artikel eingefügt - Alles, was Sie über Singleton wissen wollen


2

Es gibt einen großen Unterschied zwischen einer einzelnen statischen Klasseninstanz (dh einer einzelnen Instanz einer Klasse, die zufällig eine statische oder globale Variable ist) und einem einzelnen statischen Zeiger auf eine Instanz der Klasse auf dem Heap:

Wenn Ihre Anwendung beendet wird, wird der Destruktor der statischen Klasseninstanz aufgerufen. Das heißt, wenn Sie diese statische Instanz als Singleton verwendet haben, funktioniert Ihr Singleton nicht mehr ordnungsgemäß. Wenn noch Code ausgeführt wird, der diesen Singleton verwendet, z. B. in einem anderen Thread, stürzt dieser Code wahrscheinlich ab.


1
Wenn die Anwendung beendet wird, bleibt Singleton dann noch im Speicher?
Nanosoft

Ich denke du meinst, wenn dein aktueller Thread beendet wird, nicht die Anwendung, oder? Wenn die Anwendung beendet wird, kann ein anderer Thread nichts davon verwenden.
Tom Brito

2

Der Unterschied in meinem Kopf besteht in der Implementierung der objektorientierten Programmierung (Singleton / Prototype) oder der funktionalen Programmierung (Static).

Wir konzentrieren uns zu sehr auf die Anzahl der Objekte, die durch Singleton-Muster erstellt wurden, wenn wir uns darauf konzentrieren sollten, dass wir am Ende ein Objekt halten. Wie andere bereits gesagt haben, kann es erweitert, als Parameter übergeben werden, aber vor allem ist es zustandsreich.

Andererseits wird statisch verwendet, um eine funktionale Programmierung zu implementieren. Die statischen Elemente gehören zu einer Klasse. Sie sind staatenlos.

Wussten Sie übrigens, dass Sie statische Singleton-Klassen erstellen können :)


Was bringt es, einen Singleton als Parameter zu übergeben, da er immer einen statischen Verweis auf die Klasse hat?
Aaron Franke
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.