Sie haben sich kürzlich mit dem Singleton-Entwurfsmuster befasst , wie man es in Java implementiert und wozu es dient. Aber was ist, wenn ich Ihnen sage, dass Java standardmäßig mit einem eigenen Singleton geliefert wird? Fasziniert? Dann lasst uns eintauchen.

Sie kennen wahrscheinlich bereits die Enum-Klasse . Es gibt eine Besonderheit, die Sie beachten sollten. Konkret implementiert Enum das Singleton-Entwurfsmuster. Diese Option ist fast identisch mit dem Singleton-Ansatz mit einem öffentlichen Feld.

Singleton als Enumeration:


public enum Device {   
    PRINTER	
} 
    

Singleton als öffentliche Variable:


public class Printer {   
    public static final Printer PRINTER = new Printer();   
    private Printer() {
    }
//…
}
    

Der Enum- Ansatz ist kompakter als der Public-Field-Ansatz, da wir keine eigene Implementierung schreiben müssen. Am wichtigsten ist, dass Aufzählungen keine Probleme mit der Serialisierung haben.

Die Serialisierung von Aufzählungen funktioniert anders als bei gewöhnlichen Objekten: Nur der Wert des Aufzählungsnamens wird serialisiert. Bei der Deserialisierung wird die Methode mit dem deserialisierten Namen verwendet, um eine Instanz abzurufen. Darüber hinaus kann Enum Sie vor Reflection-Angriffen schützen .

Mehr über Reflection erfahren Sie in den Lektionen des zweiten Moduls, in dem wir uns mit der Reflection-API befassen .

Java verbietet die Instanziierung von Aufzählungen – eine Einschränkung, die in die Implementierung der newInstance- Methode der Constructor- Klasse integriert ist, die oft aufgerufen wird, wenn Objekte durch Reflektion erstellt werden.

Codeauszug aus Constructor.newInstance . Wird zum Erstellen einer Enumeration verwendet :


if ((clazz.getModifiers() & Modifier.ENUM) != 0)
    throw new IllegalArgumentException("Cannot reflectively create enum objects");
    

Zu den Nachteilen der Verwendung einer Enumeration zum Erstellen eines Singletons gehören:

  • Fehlen einer verzögerten Initialisierung, da das Objekt sofort erstellt wird und die Initialisierung nicht verzögert werden kann.

  • Andere Kurse können nicht verlängert werden. Das heißt, in Fällen, in denen Sie eine andere Klasse erben müssen, funktioniert die Verwendung einer Aufzählung als Singleton nicht. In solchen Fällen müssen wir auf die anderen uns bereits bekannten Implementierungsmöglichkeiten zurückgreifen: eine statische Methode oder eine öffentliche Variable.

  • Wenn Sie enum als Singleton verwenden, können Sie nur ein enum- Feld verwenden.


public enum Device extends Electricity { 
    PRINTER 
}
    

Dieser Code gibt uns einen Kompilierungsfehler:

Für die Enumeration ist keine Extens-Klausel zulässig

Wenn wir jedoch eine Schnittstelle implementieren müssen, gibt es kein Problem, da enum Schnittstellen implementieren kann:


public enum Device implements Electricity { 
    PRINTER 
}
    

Wenn Sie keine Vererbung verwenden müssen, implementieren Sie das Singleton-Muster am besten über enum . Wir sind nicht die Einzigen, die dies empfehlen – auch Joshua Bloch selbst empfiehlt dies .

Dieser Implementierungsansatz bietet Ihnen Komfort, Kompaktheit, sofort einsatzbereite Serialisierung, Schutz vor Reflexionsangriffen und Einzigartigkeit – alles, was ein guter Singleton braucht!