Du grävde nyligen ner i designmönstret för singelton , hur man implementerar det i Java och vad det är till för. Men vad händer om jag berättar att Java kommer med sin egen singleton ur lådan? Fascinerad? Låt oss sedan dyka in.

Du känner förmodligen redan till Enum-klassen . Den har en speciell funktion som du bör vara medveten om. Specifikt implementerar Enum singeldesignmönstret. Detta alternativ är nästan detsamma som singleton-metoden som involverar ett offentligt fält.

Singleton som enum:


public enum Device {   
    PRINTER	
} 
    

Singleton som en offentlig variabel:


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

Enum - metoden är mer kompakt än public-field-metoden, eftersom vi inte behöver skriva vår egen implementering. Viktigast av allt, enums har inga problem med serialisering.

Serialisering av enums fungerar annorlunda än för vanliga objekt: endast värdet på enumnamnet serialiseras. Under deserialisering används metoden med det deserialiserade namnet för att få en instans. Dessutom kan enum skydda dig mot reflektionsattacker .

Du kommer att lära dig mer om reflektion i lektionerna i den andra modulen, där vi kommer att utforska Reflection API .

Java förbjuder instansiering av enums — en begränsning inbakad i implementeringen av Constructor -klassens newInstance -metod, som ofta kallas när man skapar objekt genom reflektion.

Utdrag av kod från Constructor.newInstance . Används för att skapa en uppräkning :


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

Nackdelarna med att använda en enum för att skapa en singel inkluderar:

  • Brist på lat initiering, eftersom objektet skapas omedelbart och initieringen inte kan försenas.

  • Andra klasser kan inte förlängas. Det vill säga, i de fall där du behöver ärva en annan klass kommer det inte att fungera att använda en enum som singleton. I sådana fall måste vi vända oss till de andra implementeringsalternativen som vi redan känner till: en statisk metod eller en offentlig variabel.

  • När du använder enum som singleton kan du bara använda ett enum -fält.


public enum Device extends Electricity { 
    PRINTER 
}
    

Den här koden kommer att ge oss ett kompileringsfel:

Ingen förlängningsklausul tillåts för enum

Men om vi behöver implementera ett gränssnitt är det inga problem, eftersom enum kan implementera gränssnitt:


public enum Device implements Electricity { 
    PRINTER 
}
    

Om du inte behöver använda arv är det bäst att implementera singleton-mönstret via enum . Vi är inte ensamma om att rekommendera detta – Joshua Bloch själv gör det också .

Denna implementeringsmetod ger dig bekvämlighet, kompakthet, serialisering direkt, skydd mot reflektionsattacker och unikhet - allt som en bra singel behöver!