U heeft zich onlangs verdiept in het singleton-ontwerppatroon , hoe u dit in Java implementeert en waarvoor het dient. Maar wat als ik je vertel dat Java uit de doos met zijn eigen singleton wordt geleverd? Gefascineerd? Laten we er dan in duiken.

U kent de Enum-klasse waarschijnlijk al . Het heeft een speciale functie waarvan u op de hoogte moet zijn. In het bijzonder implementeert Enum het singleton-ontwerppatroon. Deze optie is bijna hetzelfde als de singleton-benadering met een openbaar veld.

Singleton als opsomming:


public enum Device {   
    PRINTER	
} 
    

Singleton als openbare variabele:


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

De enum -benadering is compacter dan de public-field-benadering, omdat we onze eigen implementatie niet hoeven te schrijven. Het belangrijkste is dat opsommingen geen problemen hebben met serialisatie.

Serialisatie van opsommingen werkt anders dan voor gewone objecten: alleen de waarde van de opsommingsnaam wordt geserialiseerd. Tijdens deserialisatie wordt de methode gebruikt met de gedeserialiseerde naam om een ​​instantie op te halen. Bovendien kan enum je beschermen tegen reflectieaanvallen .

Je leert meer over reflectie in de lessen in de tweede module, waar we de Reflection API gaan verkennen .

Java verbiedt het instantiëren van opsommingen - een beperking die is ingebakken in de implementatie van de methode newInstance van de Constructor- klasse , die vaak wordt aangeroepen bij het maken van objecten door middel van reflectie.

Uittreksel van code van Constructor.newInstance . Gebruikt om een ​​opsomming te maken :


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

De nadelen van het gebruik van een enum om een ​​singleton te maken zijn:

  • Gebrek aan luie initialisatie, aangezien het object onmiddellijk wordt gemaakt en de initialisatie niet kan worden uitgesteld.

  • Andere lessen kunnen niet verlengd worden. Dat wil zeggen, in gevallen waarin u een andere klasse moet erven, werkt het niet om een ​​enum als singleton te gebruiken. In dergelijke gevallen moeten we ons wenden tot de andere implementatie-opties die ons al bekend zijn: een statische methode of een openbare variabele.

  • Wanneer u enum als singleton gebruikt, kunt u slechts één enum- veld gebruiken.


public enum Device extends Electricity { 
    PRINTER 
}
    

Deze code geeft ons een compilatiefout:

Geen verlengclausule toegestaan ​​voor enum

Maar als we een interface moeten implementeren, is er geen probleem, aangezien enum interfaces kan implementeren:


public enum Device implements Electricity { 
    PRINTER 
}
    

Als u geen gebruik hoeft te maken van overerving, kunt u het beste het singleton-patroon implementeren via enum . We zijn niet de enigen die dit aanbevelen - Joshua Bloch doet het zelf ook .

Deze implementatiebenadering biedt u gemak, compactheid, out-of-the-box serialisatie, bescherming tegen reflectieaanvallen en uniciteit - alles wat een goede singleton nodig heeft!