Außerdem ist der Singleton eines der am häufigsten verwendeten und missbrauchten Entwurfsmuster in der OO-Programmierung.
ChaosPandion
3
@Fabiano: Weil es eine Möglichkeit gibt, Kopplungen zu erstellen, die keinen Sinn ergeben (wie kann ich Xmit ihnen sprechen Y? Machen Sie einfach Yeinen Singleton!), Was wiederum zu Schwierigkeiten beim Testen / Debuggen und einem prozeduralen Programmierstil führt. Manchmal sind Singletons notwendig; die meiste Zeit nicht.
Aaronaught
3
Dies ist eine meiner Standardfragen zu Telefoninterviews. Die richtige Antwort lautet: niemals.
Jonnii
3
@jonnii das ist gut, es hilft potenziellen Entwicklern zu warnen, wie dort Chef ist!
Mr. Boy
Antworten:
144
Ein Singleton ist eine Klasse, mit der nur eine Instanz von sich selbst erstellt werden kann - und die einen einfachen Zugriff auf diese Instanz bietet. Die Singleton-Prämisse ist ein Muster für die gesamte Softwareentwicklung.
Um ehrlich zu sein, ist es sehr selten, dass Sie einen Singleton implementieren müssen - meiner Meinung nach sollte dies eines der Dinge sein, die Sie beachten sollten, auch wenn es nicht zu oft verwendet wird.
Nicht threadsicher. Zwei Threads können gleichzeitig aufrufen und zwei separate Objekte erstellen.
Alagesan Palani
5
@ Alagesan Palani, in der Tat hast du recht. Ich bin nicht mit den Details der Initialisierung auf Klassenebene vertraut, aber ich denke, die Änderung, die ich vorgenommen habe, behebt das Thread-sichere Problem.
Chris Simmons
3
Sicher, ich zeige NICHT, dass Sie falsch liegen. Ich gebe dem Leser einen Hinweis zur Thread-Sicherheit, damit er vorsichtig ist, wenn er sich damit befassen muss.
Alagesan Palani
9
Nein, ich denke dein Kommentar ist wichtig. Da ein Singleton eine - und nur eine - Instanz liefern soll, eröffnet die Race-Bedingung hier die Möglichkeit, dass mehr als eine Instanz geliefert wird. Sehen Sie sich jetzt die Version mit statischer Feldinitialisierung an. Ich glaube, dies behebt das Thread-Sicherheitsproblem, wenn ich die Dokumente lese und diese SO richtig antworte .
Chris Simmons
1
@ AlagesanPalani, ich sehe, dass Sie angegeben haben, dass einige andere Antworten nicht threadsicher sind. Möchten Sie eine threadsichere Lösung anbieten?
Bonez024
39
Was es ist: Eine Klasse, für die es über die Lebensdauer einer Anwendung nur eine dauerhafte Instanz gibt. Siehe Singleton-Muster .
Wann Sie es verwenden sollten: So wenig wie möglich. Nur wenn Sie absolut sicher sind, dass Sie es brauchen. Ich zögere es, "nie" zu sagen, aber es gibt normalerweise eine bessere Alternative, wie z. B. Abhängigkeitsinjektion oder einfach eine statische Klasse.
Ich bin mir nicht sicher, ob eine statische Klasse eine bessere Alternative als ein Singleton ist ... es hängt wirklich von der Situation und der Sprache ab.
Marcgg
5
Statische Klassen verhalten sich nicht wie Singleton, ein Singleton kann als Parameter an Methoden übergeben werden, eine statische Klasse dagegen nicht.
TabbyCool
4
Mit marcgg einverstanden sein - Ich sehe eine statische Klasse nicht als gute Alternative zu Singletons, da Sie immer noch das Problem haben, einen Ersatz bereitzustellen, z. B. beim Testen einer Komponente, die von dieser Klasse abhängt. Ich sehe aber auch unterschiedliche Verwendungszwecke. Eine statische Klasse wird normalerweise für unabhängige Dienstprogrammfunktionen verwendet, die vom Status unabhängig sind, wobei ein Singleton eine tatsächliche Klasseninstanz ist und normalerweise einen Status speichert. Ich stimme vollkommen zu, stattdessen DI zu verwenden, und sage dann Ihrem DI-Container, dass er nur eine einzelne Instanz dieser Klasse verwenden soll.
Pete
9
Ich habe diese Antwort abgelehnt, weil sie mir keine Informationen darüber gibt, wann ich sie verwenden soll. "Nur wenn du es brauchst" gibt mir überhaupt keine Informationen für jemanden, der neu in Singletons ist.
Sergio Tapia
9
@Adkins: DI steht für Dependency Injection (Abhängigkeitsinjektion), wenn Klassenabhängigkeiten (normalerweise) über einen Konstruktor oder eine öffentliche Eigenschaft übergeben werden. DI allein löst das "Distanz" -Problem nicht, wird jedoch normalerweise zusammen mit einem IoC-Container (Inversion-of-Control) implementiert, der weiß, wie Abhängigkeiten automatisch initialisiert werden. Wenn Sie also einen Singleton erstellen, um das Problem "X weiß nicht, wie man Y findet / mit Y spricht" zu lösen, kann eine Kombination aus DI und IoC dasselbe Problem mit einer lockeren Kopplung lösen.
Aaronaught
27
Eine andere Möglichkeit, Singleton in c # zu implementieren, ist mir persönlich vorzuziehen, da Sie anstelle einer Methode auf die Instanz der Singeton-Klasse als Eigenschaft zugreifen können.
Nicht threadsicher. Zwei Threads können gleichzeitig aufrufen und zwei separate Objekte erstellen.
Alagesan Palani
11
using System;
using System.Collections.Generic;classMainApp{staticvoidMain(){LoadBalancer oldbalancer =null;for(int i =0; i <15; i++){LoadBalancer balancerNew =LoadBalancer.GetLoadBalancer();if(oldbalancer == balancerNew && oldbalancer !=null){Console.WriteLine("{0} SameInstance {1}", oldbalancer.Server, balancerNew.Server);}
oldbalancer = balancerNew;}Console.ReadKey();}}classLoadBalancer{privatestaticLoadBalancer _instance;privateList<string> _servers =newList<string>();privateRandom _random =newRandom();privatestaticobject syncLock =newobject();privateLoadBalancer(){
_servers.Add("ServerI");
_servers.Add("ServerII");
_servers.Add("ServerIII");
_servers.Add("ServerIV");
_servers.Add("ServerV");}publicstaticLoadBalancerGetLoadBalancer(){if(_instance ==null){lock(syncLock){if(_instance ==null){
_instance =newLoadBalancer();}}}return _instance;}publicstringServer{get{int r = _random.Next(_servers.Count);return _servers[r].ToString();}}}
Ich habe Code von dofactory.com genommen , nichts Besonderes , aber ich finde das weitaus besser als Beispiele mit Foo und Bar Buch von Judith Bishop über C # 3.0 Design Patterns enthält ein Beispiel für eine aktive Anwendung im Mac-Dock.
Wenn Sie sich Code ansehen, bauen wir tatsächlich neue Objekte für die for- Schleife auf, sodass ein neues Objekt erstellt wird, die Instanz jedoch wiederverwendet wird, wodurch der alte und der neue Balancer dieselbe Instanz haben. Wie? Dies ist auf das statische Schlüsselwort zurückzuführen, das für die Funktion GetLoadBalancer () verwendet wird. Trotz des unterschiedlichen Serverwerts , der eine zufällige Liste ist, ist das statische Schlüsselwort für GetLoadBalancer () zum Typ selbst und nicht zu einem bestimmten Objekt .
Das Schlüsselwort lock stellt sicher, dass ein Thread keinen kritischen Codeabschnitt eingibt, während sich ein anderer Thread im kritischen Abschnitt befindet. Wenn ein anderer Thread versucht, einen gesperrten Code einzugeben, wartet er blockiert, bis das Objekt freigegeben wird.
Daher wird jedes Mal eine Sperre für den gegenseitigen Ausschluss ausgestellt, auch wenn dies nicht erforderlich ist. Dies ist nicht erforderlich, sodass wir eine Nullprüfung durchführen.
Hoffentlich hilft es beim Löschen von mehr.
Und bitte kommentieren Sie, wenn mein Verständnis falsche Wege weist.
Ein Singleton (und dies ist nicht an C # gebunden, es ist ein OO-Entwurfsmuster) ist, wenn Sie zulassen möchten, dass nur EINE Instanz einer Klasse in Ihrer Anwendung erstellt wird. Die Nutzung umfasst normalerweise globale Ressourcen, obwohl ich aus persönlicher Erfahrung sagen werde, dass sie sehr oft die Quelle großer Schmerzen sind.
Während es immer nur eine Instanz eines Singletons geben kann, ist dies nicht dasselbe wie eine statische Klasse. Eine statische Klasse kann nur statische Methoden enthalten und kann niemals instanziiert werden, während die Instanz eines Singletons auf dieselbe Weise wie jedes andere Objekt verwendet werden kann.
Es ist ein Designmuster und nicht spezifisch für c #. Mehr darüber im Internet und SO, wie in diesem Wikipedia-Artikel .
In der Softwareentwicklung ist das Singleton-Muster ein Entwurfsmuster, mit dem die Instanziierung einer Klasse auf ein Objekt beschränkt wird. Dies ist nützlich, wenn genau ein Objekt benötigt wird, um Aktionen im gesamten System zu koordinieren. Das Konzept wird manchmal auf Systeme verallgemeinert, die effizienter arbeiten, wenn nur ein Objekt vorhanden ist, oder die die Instanziierung auf eine bestimmte Anzahl von Objekten beschränken (z. B. fünf). Einige halten es für ein Anti-Pattern, da es zu häufig verwendet wird, unnötige Einschränkungen in Situationen einführt, in denen eine einzige Instanz einer Klasse nicht erforderlich ist, und den globalen Status in eine Anwendung einführt.
Sie sollten es verwenden, wenn Sie eine Klasse möchten, die nur einmal instanziiert werden kann.
Was ist ein Singleton?
Es ist eine Klasse, die nur die Erstellung einer Instanz von sich selbst ermöglicht und normalerweise einen einfachen Zugriff auf diese Instanz ermöglicht.
Wann sollten Sie verwenden:
Es hängt von der Situation ab.
Hinweis: Bitte auf DB - Verbindung nicht verwenden, für eine ausführliche Antwort bitte beziehen sich auf die Antwort von @Chad Grants
Hier ist ein einfaches Beispiel für Singleton:
publicsealedclassSingleton{privatestaticreadonlySingleton instance =newSingleton();// Explicit static constructor to tell C# compiler// not to mark type as beforefieldinitstaticSingleton(){}privateSingleton(){}publicstaticSingletonInstance{get{return instance;}}}
Sie können auch verwenden Lazy<T>, um Ihre zu erstellen Singleton.
Hier finden Sie ein detaillierteres Beispiel für die VerwendungLazy<T>
In diesem Artikel wird beschrieben, wie wir mit schreibgeschützten Variablen eine thread-sichere Singleton-Klasse erstellen können und wie sie in Anwendungen praktisch eingesetzt werden können.
EX Sie können Singleton für globale Informationen verwenden, die injiziert werden müssen.
In meinem Fall habe ich die Details des protokollierten Benutzers (Benutzername, Berechtigungen usw.) in der globalen statischen Klasse gespeichert. Und als ich versuchte, den Unit Test zu implementieren, konnte ich keine Abhängigkeit in Controller-Klassen einfügen. Daher habe ich meine statische Klasse in ein Singleton-Muster geändert.
Wir müssen das Singleton-Entwurfsmuster in C # verwenden, um sicherzustellen, dass nur eine Instanz einer bestimmten Klasse erstellt wird, und dann für die gesamte Anwendung einen einfachen globalen Zugriff auf diese Instanz bereitzustellen.
Echtzeitszenarien, in denen Sie das Singleton-Entwurfsmuster verwenden können: Service-Proxies: Wie wir wissen, ist das Aufrufen einer Service-API eine umfangreiche Operation in einer Anwendung. Der Prozess, der die meiste Zeit in Anspruch nimmt, ist das Erstellen des Service-Clients, um die Service-API aufzurufen. Wenn Sie den Service-Proxy als Singleton erstellen, wird die Leistung Ihrer Anwendung verbessert.
Fassaden: Sie können die Datenbankverbindungen auch als Singleton erstellen, um die Leistung der Anwendung zu verbessern.
Protokolle: In einer Anwendung ist das Ausführen der E / A-Operation für eine Datei eine teure Operation. Wenn Sie Ihren Logger als Singleton erstellen, wird die Leistung der E / A-Operation verbessert.
Datenfreigabe: Wenn Sie konstante Werte oder Konfigurationswerte haben, können Sie diese Werte in Singleton behalten, damit diese von anderen Komponenten der Anwendung gelesen werden können.
Caching: Wie wir wissen, ist das Abrufen der Daten aus einer Datenbank ein zeitaufwändiger Prozess. In Ihrer Anwendung können Sie den Master und die Konfiguration im Speicher zwischenspeichern, um die DB-Aufrufe zu vermeiden. In solchen Situationen kann die Singleton-Klasse verwendet werden, um das Caching mit Thread-Synchronisation auf effiziente Weise zu handhaben, wodurch die Leistung der Anwendung drastisch verbessert wird.
Nachteile des Singleton-Entwurfsmusters in C # Die Nachteile der Verwendung des Singleton-Entwurfsmusters in C # sind folgende:
Unit-Tests sind sehr schwierig, da sie einen globalen Status in eine Anwendung einführen. Dies verringert das Potenzial für Parallelität innerhalb eines Programms, da für den Zugriff auf die Singleton-Instanz in einer Umgebung mit mehreren Threads das Objekt mithilfe der Sperre serialisiert werden muss.
X
mit ihnen sprechenY
? Machen Sie einfachY
einen Singleton!), Was wiederum zu Schwierigkeiten beim Testen / Debuggen und einem prozeduralen Programmierstil führt. Manchmal sind Singletons notwendig; die meiste Zeit nicht.Antworten:
Ein Singleton ist eine Klasse, mit der nur eine Instanz von sich selbst erstellt werden kann - und die einen einfachen Zugriff auf diese Instanz bietet. Die Singleton-Prämisse ist ein Muster für die gesamte Softwareentwicklung.
Es gibt eine C # -Implementierung "Implementieren des Singleton-Musters in C #", die das meiste abdeckt, was Sie wissen müssen - einschließlich einiger guter Ratschläge zur Thread-Sicherheit .
Um ehrlich zu sein, ist es sehr selten, dass Sie einen Singleton implementieren müssen - meiner Meinung nach sollte dies eines der Dinge sein, die Sie beachten sollten, auch wenn es nicht zu oft verwendet wird.
quelle
Lazy<T> Class
.Sie haben nach C # gefragt. Triviales Beispiel:
quelle
Was es ist: Eine Klasse, für die es über die Lebensdauer einer Anwendung nur eine dauerhafte Instanz gibt. Siehe Singleton-Muster .
Wann Sie es verwenden sollten: So wenig wie möglich. Nur wenn Sie absolut sicher sind, dass Sie es brauchen. Ich zögere es, "nie" zu sagen, aber es gibt normalerweise eine bessere Alternative, wie z. B. Abhängigkeitsinjektion oder einfach eine statische Klasse.
quelle
Eine andere Möglichkeit, Singleton in c # zu implementieren, ist mir persönlich vorzuziehen, da Sie anstelle einer Methode auf die Instanz der Singeton-Klasse als Eigenschaft zugreifen können.
Aber soweit ich weiß, werden beide Wege als "richtig" angesehen, also ist es nur eine Sache des persönlichen Geschmacks.
quelle
Ich habe Code von dofactory.com genommen , nichts Besonderes , aber ich finde das weitaus besser als Beispiele mit Foo und Bar Buch von Judith Bishop über C # 3.0 Design Patterns enthält ein Beispiel für eine aktive Anwendung im Mac-Dock.
Wenn Sie sich Code ansehen, bauen wir tatsächlich neue Objekte für die for- Schleife auf, sodass ein neues Objekt erstellt wird, die Instanz jedoch wiederverwendet wird, wodurch der alte und der neue Balancer dieselbe Instanz haben. Wie? Dies ist auf das statische Schlüsselwort zurückzuführen, das für die Funktion GetLoadBalancer () verwendet wird. Trotz des unterschiedlichen Serverwerts , der eine zufällige Liste ist, ist das statische Schlüsselwort für GetLoadBalancer () zum Typ selbst und nicht zu einem bestimmten Objekt .
Zusätzlich gibt es überprüfen Sperren hier
seit von MSDN
Daher wird jedes Mal eine Sperre für den gegenseitigen Ausschluss ausgestellt, auch wenn dies nicht erforderlich ist. Dies ist nicht erforderlich, sodass wir eine Nullprüfung durchführen.
Hoffentlich hilft es beim Löschen von mehr.
Und bitte kommentieren Sie, wenn mein Verständnis falsche Wege weist.
quelle
Ein Singleton (und dies ist nicht an C # gebunden, es ist ein OO-Entwurfsmuster) ist, wenn Sie zulassen möchten, dass nur EINE Instanz einer Klasse in Ihrer Anwendung erstellt wird. Die Nutzung umfasst normalerweise globale Ressourcen, obwohl ich aus persönlicher Erfahrung sagen werde, dass sie sehr oft die Quelle großer Schmerzen sind.
quelle
Während es immer nur eine Instanz eines Singletons geben kann, ist dies nicht dasselbe wie eine statische Klasse. Eine statische Klasse kann nur statische Methoden enthalten und kann niemals instanziiert werden, während die Instanz eines Singletons auf dieselbe Weise wie jedes andere Objekt verwendet werden kann.
quelle
Es ist ein Designmuster und nicht spezifisch für c #. Mehr darüber im Internet und SO, wie in diesem Wikipedia-Artikel .
Sie sollten es verwenden, wenn Sie eine Klasse möchten, die nur einmal instanziiert werden kann.
quelle
Ich benutze es für Suchdaten. Einmal aus DB laden.
quelle
Was ist ein Singleton?
Es ist eine Klasse, die nur die Erstellung einer Instanz von sich selbst ermöglicht und normalerweise einen einfachen Zugriff auf diese Instanz ermöglicht.
Wann sollten Sie verwenden:
Es hängt von der Situation ab.
Hinweis: Bitte auf DB - Verbindung nicht verwenden, für eine ausführliche Antwort bitte beziehen sich auf die Antwort von @Chad Grants
Hier ist ein einfaches Beispiel für
Singleton
:Sie können auch verwenden
Lazy<T>
, um Ihre zu erstellenSingleton
.Hier finden Sie ein detaillierteres Beispiel für die Verwendung
Lazy<T>
quelle
Folgendes ist Singleton: http://en.wikipedia.org/wiki/Singleton_pattern
Ich kenne C # nicht, aber es ist in allen Sprachen dasselbe, nur die Implementierung unterscheidet sich.
Sie sollten Singleton generell vermeiden, wenn es möglich ist, aber in einigen Situationen ist es sehr praktisch.
Entschuldigung für mein Englisch ;)
quelle
Die Singleton-Klasse wird verwendet, um eine einzelne Instanz für die gesamte Anwendungsdomäne zu erstellen.
In diesem Artikel wird beschrieben, wie wir mit schreibgeschützten Variablen eine thread-sichere Singleton-Klasse erstellen können und wie sie in Anwendungen praktisch eingesetzt werden können.
quelle
Ich weiß, dass es sehr spät ist, die Frage zu beantworten, aber mit Auto-Property können Sie so etwas tun:
public static Singleton Instance { get; } = new Singleton();
Wo
Singleton
ist Ihre Klasse und kann über, in diesem Fall die schreibgeschützte Eigenschaft seinInstance
.quelle
EX Sie können Singleton für globale Informationen verwenden, die injiziert werden müssen.
In meinem Fall habe ich die Details des protokollierten Benutzers (Benutzername, Berechtigungen usw.) in der globalen statischen Klasse gespeichert. Und als ich versuchte, den Unit Test zu implementieren, konnte ich keine Abhängigkeit in Controller-Klassen einfügen. Daher habe ich meine statische Klasse in ein Singleton-Muster geändert.
http://csharpindepth.com/Articles/General/Singleton.aspx#cctor
quelle
Wir müssen das Singleton-Entwurfsmuster in C # verwenden, um sicherzustellen, dass nur eine Instanz einer bestimmten Klasse erstellt wird, und dann für die gesamte Anwendung einen einfachen globalen Zugriff auf diese Instanz bereitzustellen.
Echtzeitszenarien, in denen Sie das Singleton-Entwurfsmuster verwenden können: Service-Proxies: Wie wir wissen, ist das Aufrufen einer Service-API eine umfangreiche Operation in einer Anwendung. Der Prozess, der die meiste Zeit in Anspruch nimmt, ist das Erstellen des Service-Clients, um die Service-API aufzurufen. Wenn Sie den Service-Proxy als Singleton erstellen, wird die Leistung Ihrer Anwendung verbessert.
Fassaden: Sie können die Datenbankverbindungen auch als Singleton erstellen, um die Leistung der Anwendung zu verbessern.
Protokolle: In einer Anwendung ist das Ausführen der E / A-Operation für eine Datei eine teure Operation. Wenn Sie Ihren Logger als Singleton erstellen, wird die Leistung der E / A-Operation verbessert.
Datenfreigabe: Wenn Sie konstante Werte oder Konfigurationswerte haben, können Sie diese Werte in Singleton behalten, damit diese von anderen Komponenten der Anwendung gelesen werden können.
Caching: Wie wir wissen, ist das Abrufen der Daten aus einer Datenbank ein zeitaufwändiger Prozess. In Ihrer Anwendung können Sie den Master und die Konfiguration im Speicher zwischenspeichern, um die DB-Aufrufe zu vermeiden. In solchen Situationen kann die Singleton-Klasse verwendet werden, um das Caching mit Thread-Synchronisation auf effiziente Weise zu handhaben, wodurch die Leistung der Anwendung drastisch verbessert wird.
Nachteile des Singleton-Entwurfsmusters in C # Die Nachteile der Verwendung des Singleton-Entwurfsmusters in C # sind folgende:
Unit-Tests sind sehr schwierig, da sie einen globalen Status in eine Anwendung einführen. Dies verringert das Potenzial für Parallelität innerhalb eines Programms, da für den Zugriff auf die Singleton-Instanz in einer Umgebung mit mehreren Threads das Objekt mithilfe der Sperre serialisiert werden muss.
Ich habe dies dem folgenden Artikel entnommen.
https://dotnettutorials.net/lesson/singleton-design-pattern/
quelle
Thread Safe Singleton ohne Verwendung von Sperren und ohne verzögerte Instanziierung.
Diese Implementierung verfügt über einen statischen Konstruktor, sodass sie nur einmal pro Anwendungsdomäne ausgeführt wird.
quelle