Alcuni problemi con i singoli enum:
Impegnarsi in una strategia di attuazione
In genere, "singleton" si riferisce a una strategia di implementazione, non a una specifica API. È molto raro Foo1.getInstance()dichiarare pubblicamente che restituirà sempre la stessa istanza. Se necessario, l'implementazione di Foo1.getInstance()può evolversi, ad esempio, per restituire un'istanza per thread.
Con Foo2.INSTANCEdichiariamo pubblicamente che questa istanza è l' istanza e non c'è alcuna possibilità di cambiarla. La strategia di implementazione di avere una singola istanza è esposta e impegnata.
Questo problema non è paralizzante. Ad esempio, Foo2.INSTANCE.doo()può fare affidamento su un oggetto helper locale di thread per disporre effettivamente di un'istanza per thread.
Estensione della classe Enum
Foo2estende una super classe Enum<Foo2>. Di solito vogliamo evitare le super classi; specialmente in questo caso, la superclasse forzata Foo2non ha nulla a che fare con ciò che Foo2dovrebbe essere. Questo è un inquinamento per la gerarchia dei tipi della nostra applicazione. Se vogliamo davvero una super classe, di solito è una classe di applicazione, ma non possiamo,Foo2 la superclasse è fissa.
Foo2eredita alcuni metodi di istanza divertenti come name(), cardinal(), compareTo(Foo2), che sono solo fonte di confusione per Foo2gli utenti. Foo2non può avere il proprio name()metodo anche se tale metodo è desiderabile Foo2nell'interfaccia di.
Foo2 contiene anche alcuni metodi statici divertenti
public static Foo2[] values() { ... }
public static Foo2 valueOf(String name) { ... }
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
che sembra essere privo di senso per gli utenti. Un singleton di solito non dovrebbe avere comunque metodi statici pulbici (diversi dai getInstance())
serializzabilità
È molto comune che i singoli siano con stato. Questi singleton generalmente non dovrebbero essere serializzabili. Non riesco a pensare a nessun esempio realistico in cui abbia senso trasportare un singleton con stato da una VM a un'altra VM; un singleton significa "unico all'interno di una VM", non "unico nell'universo".
Se la serializzazione ha davvero senso per un singleton con stato, il singleton dovrebbe specificare in modo esplicito e preciso cosa significa deserializzare un singleton in un'altra VM in cui potrebbe già esistere un singleton dello stesso tipo.
Foo2si impegna automaticamente in una strategia di serializzazione / deserializzazione semplicistica. Questo è solo un incidente in attesa di accadere. Se abbiamo un albero di dati che fa riferimento concettualmente a una variabile di stato Foo2in VM1 at t1, attraverso la serializzazione / deserializzazione il valore diventa un valore diverso - il valore della stessa variabile di Foo2in VM2 at t2, creando un bug difficile da rilevare. Questo bug non accadrà Foo1silenziosamente all'inserializzabile .
Restrizioni alla codifica
Ci sono cose che possono essere fatte in classi normali, ma vietate in enumclasse. Ad esempio, l'accesso a un campo statico nel costruttore. Il programmatore deve stare più attento poiché lavora in una classe speciale.
Conclusione
Salvando su enum, salviamo 2 righe di codice; ma il prezzo è troppo alto, dobbiamo portare tutti i bagagli e le restrizioni degli enum, ereditiamo inavvertitamente "caratteristiche" dell'enum che hanno conseguenze indesiderate. L'unico presunto vantaggio - serializzabilità automatica - risulta essere uno svantaggio.