Kamakailan mong sinilip ang singleton na pattern ng disenyo , kung paano ito ipatupad sa Java, at para saan ito. Ngunit paano kung sabihin ko sa iyo na ang Java ay may sarili nitong singleton sa labas ng kahon? naiintriga? Pagkatapos ay sumisid tayo.

Malamang alam mo na ang tungkol sa klase ng Enum . Mayroon itong espesyal na tampok na dapat mong malaman. Sa partikular, ipinapatupad ng Enum ang pattern ng disenyo ng singleton. Ang opsyong ito ay halos kapareho ng singleton approach na kinasasangkutan ng pampublikong field.

Singleton bilang enum:


public enum Device {   
    PRINTER	
} 
    

Singleton bilang isang pampublikong variable:


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

Ang enum approach ay mas compact kaysa sa public-field approach, dahil hindi namin kailangang magsulat ng sarili naming pagpapatupad. Ang pinakamahalaga, ang mga enum ay walang problema sa serialization.

Iba ang paggana ng serialization ng mga enum kaysa sa mga ordinaryong bagay: ang value lang ng pangalan ng enum ang naka-serialize. Sa panahon ng deserialization, ang paraan ay ginagamit sa deserialized na pangalan upang makakuha ng isang instance. Bukod pa rito, mapoprotektahan ka ng enum laban sa mga pag-atake ng reflection .

Matututunan mo ang higit pa tungkol sa pagmuni-muni sa mga aralin sa ikalawang module, kung saan tutuklasin natin ang Reflection API .

Ipinagbabawal ng Java ang pag-instantiate ng mga enum —isang limitasyong inilagay sa pagpapatupad ng bagong Instance na pamamaraan ng Constructor class , na kadalasang tinatawag kapag lumilikha ng mga bagay sa pamamagitan ng pagmuni-muni.

Sipi ng code mula sa Constructor.newInstance . Ginamit upang lumikha ng isang enum :


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

Ang mga disadvantages ng paggamit ng isang enum upang lumikha ng isang singleton ay kinabibilangan ng:

  • Kakulangan ng tamad na pagsisimula, dahil ang bagay ay nilikha kaagad at ang pagsisimula ay hindi maaaring maantala.

  • Hindi maaaring i-extend ang ibang klase. Iyon ay, sa mga kaso kung saan kailangan mong magmana ng isa pang klase, hindi gagana na gumamit ng enum bilang singleton. Sa ganitong mga kaso, kailangan naming bumaling sa iba pang mga opsyon sa pagpapatupad na pamilyar sa amin: isang static na paraan o isang pampublikong variable.

  • Kapag gumagamit ng enum bilang singleton, maaari ka lang gumamit ng isang enum field.


public enum Device extends Electricity { 
    PRINTER 
}
    

Ang code na ito ay magbibigay sa amin ng isang compilation error:

Walang pinahihintulutang sugnay para sa enum

Ngunit kung kailangan nating magpatupad ng isang interface, walang problema, dahil ang enum ay maaaring magpatupad ng mga interface:


public enum Device implements Electricity { 
    PRINTER 
}
    

Kung hindi mo kailangang gumamit ng inheritance, pinakamahusay na ipatupad ang singleton pattern sa pamamagitan ng enum . Hindi kami nag-iisa sa pagrerekomenda nito — si Joshua Bloch mismo ang gumagawa din .

Ang diskarte sa pagpapatupad na ito ay nagbibigay sa iyo ng kaginhawahan, pagiging compact, serialization sa labas ng kahon, proteksyon mula sa mga pag-atake sa pagmuni-muni, at pagiging natatangi — lahat ng kailangan ng isang magaling na singleton!