2009-02-12 15 views
5

Come per la progettazione, una costante enum in java è un singleton e, per motivi di utilizzo simultaneo, di solito creo istanze di enum stateless e utilizzo i parametri del metodo per iniettare i dati secondo necessità.Gli oggetti enum dovrebbero essere apolidi?

Esempio:

Attualmente sto creando un servizio REST che ha Operations (implementato come un enum utilizzando una variante del modello di strategia).

public enum Operation { 

    DO_THIS() { 
    public Result doSomething(Object theData) { 
    } 
    } , 
    // Other Operations go here 
    ; 

    public abstract Result doSomething(Object theData); 

} 

Ora voglio raccogliere dati su quanto spesso è stata chiamata un'operazione e con quale frequenza ha avuto successo e simili.

È possibile salvare lo stato esternamente quando si utilizza l'istanza di enum, ma sembra piuttosto che lo stato debba essere salvato nell'operazione in quanto l'operazione deve contenere il proprio stato.

Ora la mia domanda generale è:

è un'istanza enum stateful (oltre da problemi di concorrenza) un cattivo design?

+0

senza domande, sì. – user924272

risposta

18

Penso che violi il Principio di Almost Astonishment.

Le persone si aspettano l'uso comune di enum come sono state originariamente progettate - come costanti o token, e non come classi di scopo generale con stato.

+0

Al contrario di questo enum i membri sono in effetti istanze di oggetti java di prima classe, in quanto tali possono avere metodi e variabili. Quindi forse l'intero disegno dell'enum potrebbe essere difettoso? – dhiller

+0

Penso che la ragione per cui i progettisti Java hanno utilizzato le classi per Enum è perché consentono l'univocità di riferimento (in altre parole, == funzionerebbe). Lo scenario ideale sarebbe quello di utilizzare qualcosa come "simboli", ma poi avrebbero bisogno del supporto JVM e sono troppo grandi per cambiare. – mparaz

+1

@mparaz: no, i progettisti Java hanno creato enumerazioni come le classi per consentire loro di avere un comportamento, che riguarda l'unica caratteristica linguistica di Java che mi manca in C#. Le enumerazioni con il comportamento sono fantastiche. – cletus

1

Questo sembra un cattivo uso per le enumerazioni - perché non seguire una classe astratta di base con una nuova sottoclasse per ogni operazione?

+0

perché l'operazione in quanto tale è fissa, la conversione in un tipo di operazione e l'uso di una fabbrica mi sembrano troppo eccessivi ... – dhiller

+0

Penso che potresti essere prematuramente ottimizzando - non c'è niente di sbagliato nell'usare una fabbrica e infatti farai il tuo codice è molto più facile da testare. –

7

Sì. E con "si" intendo "sempre".

Se si desidera confrontare le statistiche sul numero di operazioni richiamate, implementare qualche osservabilità.

+0

Ci penserò. Al momento la mia idea sarebbe quella di aggiungere un'istanza di StateContainer alla firma del metodo ... – dhiller

+0

+1 alla parte osservabilità della risposta. – Chii

+0

Attendi. Se aggiungi osservabilità all'enum, lo hai appena reso statico! –

4

Qualsiasi forma di statica mutabile è un peccato. (Beh, potresti farcela con cache senza perdite, qualche pigro processo di inizializzazione e forme di registrazione.)

1

Sono completamente d'accordo con mparaz che viola il Principio di Minore Stupore. La gente si aspetta che le enumerie siano costanti.

si può quasi certamente lavorare intorno alla cosa di registrazione, da qualcosa come:

DO_THIS() { 
    public Result doSomething(Object theData) { 
    MyUtilClass.doSomething(Object theData); 
    } 
} 

e mettere la vostra registrazione in altra classe.

TUTTAVIA se non si riesce a lavorare su questo, il Principio di Almostonment è una linea guida; puoi violarlo FORNITO se dai agli utenti della classe abbastanza avvertimenti su cosa sta succedendo. Assicurati che la dichiarazione Enum contenga un GRANDE avviso che dice che è mutabile e che descrive esattamente qual è la mutabilità. L'Enum dovrebbe ancora funzionare; sta facendo un confronto di riferimento con una singola istanza per testare i valori enum.

10

Un gattino muore ogni volta che crei un enum mutabile. Salva i gattini!

+0

Almeno abbiamo salvato un gruppo equo dopo aver forzato tutte le enumerazioni a essere definitive ... – Whimusical

+2

Risposta inaccettabile nella forma attuale. Si prega di fornire prove probatorie ed empiriche! – user924272

4

Una enumerazione statica è un ossimoro, persino un anti-modello!

http://en.wikipedia.org/wiki/Enumeration

Un'enumerazione è un insieme di elementi che è un sistema completo, ordinato elenco di tutti gli elementi di quella collezione. Il termine è comunemente usato in matematica e informatica teorica per fare riferimento a un elenco di tutti gli elementi di un insieme. Nelle statistiche viene usato il termine variabile categoriale piuttosto che enumerazione. I requisiti precisi per un'enumerazione (ad esempio, se l'insieme deve essere finito, o se l'elenco può contenere ripetizioni) dipendono dal ramo della matematica e dal contesto in cui si sta lavorando.

Le enumerazioni hanno un numero finito di valori, che dovrebbero essere costanti, quali sono.

Tuttavia, il fatto che si tratti di oggetti Java di "prima classe" è totalmente contrario all'intenzione o allo spirito di un'enumerazione.

Se è richiesto un qualsiasi tipo di stato, l'enum (come menzionato in precedenza) deve contenere lo stato in un Aspetto o l'enumerazione offendente, dovrebbe, per lo meno pratico, contenere un riferimento a uno stato di possesso di una classe delegata. Comprendere la "separazione delle preoccupazioni" aiuterà.

0

C'è un caso che probabilmente lo giustificherebbe. Un enum può implementare un'interfaccia, solitamente con particolare attenzione al caso particolare che consente di creare in runtime/apertamente "alcuni altri tipi della classe enum" in modo dinamico, per nominarlo in qualche modo.

Ciò significa che le istanze di enum "singleton" possono essere forzate ad implementare alcune firme di metodo destinate alla mutevole (come setter), che ovviamente è possibile nascondere con un codice vuoto o con NotSupportedException.

Fortunatamente, i metodi finali in un'interfaccia non consentono alcuna possibilità di cambiare stato. Quello sarebbe stato l'unico caso "comprensibile" che avrei potuto inventare.

Problemi correlati