
Wat is een singleton in Java?
Singleton is een van de eenvoudigste ontwerppatronen op klasseniveau. Soms zeggen mensen "deze klasse is singleton", wat betekent dat de klasse het singleton-ontwerppatroon implementeert. Soms is het nodig om een klasse te schrijven waarbij we de instantiëring beperken tot een enkel object. Bijvoorbeeld een klasse die verantwoordelijk is voor het loggen of verbinden met een database. Het singleton-ontwerppatroon beschrijft hoe we dit kunnen bereiken. Een singleton is een ontwerppatroon dat twee dingen doet:-
Het garandeert dat er maar één instantie van de klasse zal zijn.
-
Het biedt een enkel punt voor wereldwijde toegang tot die instantie.
-
Een particuliere constructeur. Dit beperkt de mogelijkheid om objecten van de klasse buiten de klasse zelf te maken.
-
Een openbare statische methode die de instantie van de klasse retourneert. Deze methode wordt getInstance genoemd . Dit is het punt van globale toegang tot de klasse-instantie.
Implementatie opties
Het singleton-ontwerppatroon wordt op verschillende manieren toegepast. Elke optie is op zijn eigen manier goed en slecht. Zoals altijd is er hier geen perfecte optie, maar we moeten ernaar streven. Laten we eerst eens kijken wat goed en slecht is, en welke maatstaven van invloed zijn op hoe we de verschillende implementaties van het ontwerppatroon beoordelen. Laten we beginnen met het goede. Hier zijn factoren die een implementatie sappiger en aantrekkelijker maken:-
Luie initialisatie: de instantie wordt pas gemaakt als deze nodig is.
-
Eenvoudige en transparante code: deze statistiek is natuurlijk subjectief, maar wel belangrijk.
-
Draadveiligheid: juiste werking in een omgeving met meerdere threads.
-
Hoge prestaties in een omgeving met meerdere threads: weinig of geen threadblokkering bij het delen van een bron.
-
Geen luie initialisatie: wanneer de klasse wordt geladen wanneer de applicatie start, ongeacht of het nodig is of niet (paradoxaal genoeg is het in de IT-wereld beter om lui te zijn)
-
Complexe en moeilijk leesbare code. Deze statistiek is ook subjectief. Als je ogen beginnen te bloeden, gaan we ervan uit dat de implementatie niet de beste is.
-
Gebrek aan draadveiligheid. Met andere woorden, "draadgevaar". Onjuiste werking in een omgeving met meerdere threads.
-
Slechte prestaties in een omgeving met meerdere threads: threads blokkeren elkaar de hele tijd of vaak bij het delen van een bron.
Code
Nu zijn we klaar om verschillende implementatieopties te overwegen en de voor- en nadelen aan te geven:Eenvoudig
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
De eenvoudigste uitvoering. Voordelen:
-
Eenvoudige en transparante code
-
Draad veiligheid
-
Hoge prestaties in een omgeving met meerdere threads
- Geen luie initialisatie.
Luie initialisatie
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Voordelen:
-
Luie initialisatie.
-
Niet draadveilig
Gesynchroniseerde toegang
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Voordelen:
-
Luie initialisatie.
-
Draad veiligheid
-
Slechte multithreaded prestaties
Dubbel gecontroleerde vergrendeling
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
Voordelen:
-
Luie initialisatie.
-
Draad veiligheid
-
Hoge prestaties in een omgeving met meerdere threads
-
Niet ondersteund in eerdere versies van Java onder 1.5 (het gebruik van vluchtig trefwoord is opgelost sinds versie 1.5)
Klasse houder
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}
Voordelen:
-
Luie initialisatie.
-
Draad veiligheid.
-
Hoge prestaties in een omgeving met meerdere threads.
-
Correcte werking vereist een garantie dat het singleton- object foutloos wordt geïnitialiseerd. Anders resulteert de eerste aanroep van de methode getInstance in een ExceptionInInitializerError en alle volgende aanroepen produceren een NoClassDefFoundError .
Implementatie | Luie initialisatie | Draad veiligheid | Multithreaded-prestaties | Wanneer te gebruiken? |
---|---|---|---|---|
Eenvoudig | - | + | Snel | Nooit. Of mogelijk wanneer luie initialisatie niet belangrijk is. Maar nooit zou beter zijn. |
Luie initialisatie | + | - | Niet toepasbaar | Altijd als multithreading niet nodig is |
Gesynchroniseerde toegang | + | + | Langzaam | Nooit. Of mogelijk wanneer multithreaded prestaties er niet toe doen. Maar nooit zou beter zijn. |
Dubbel gecontroleerde vergrendeling | + | + | Snel | In zeldzame gevallen wanneer u uitzonderingen moet afhandelen bij het maken van de singleton (wanneer de klassehouder singleton niet van toepassing is) |
Klasse houder | + | + | Snel | Telkens wanneer multithreading nodig is en er een garantie is dat het singleton-object zonder problemen wordt gemaakt. |
Voors en tegens van het singleton-patroon
Over het algemeen doet een singleton precies wat er van wordt verwacht:-
Het garandeert dat er maar één instantie van de klasse zal zijn.
-
Het biedt een enkel punt voor wereldwijde toegang tot die instantie.
-
Een singleton schendt het single responsibility-principe: naast zijn directe taken controleert de singleton-klasse ook het aantal instanties.
-
De afhankelijkheid van een gewone klas van een singleton is niet zichtbaar in het openbare contract van de klas.
-
Globale variabelen zijn slecht. Uiteindelijk verandert een singleton in een forse globale variabele.
-
De aanwezigheid van een singleton vermindert de testbaarheid van de applicatie als geheel en de klassen die de singleton in het bijzonder gebruiken.
GO TO FULL VERSION