2013-05-20 13 views
6

Mi chiedo solo se quello che sto facendo è un design in qualche modo scadente.Java: tutto in una classe è statico - è ragionevole?

Ho una lista di cose. Ho bisogno che questa lista esista sempre. Ho solo bisogno di avere una di queste liste. Ho anche alcuni metodi per interagire con questo elenco. Di conseguenza, ho reso tutto statico.

Il fatto è che poiché tutte queste cose sono nascoste in una singola classe, letteralmente tutto in quella classe viene dichiarato statico. Il che sembra un po 'strano, perché è come se volessi che l'intera classe fosse statica.

I fatti che Java non mi consente di creare un'intera classe statica e che mi è stato insegnato a ridurre al minimo i metodi statici nel mio codice sono la causa di alcuni campanelli d'allarme nella mia testa, ma onestamente non riesco a vederli ragione razionale perché quello che sto facendo non funzionerà bene.

EDIT: Un po 'di più sul programma e sul perché ho deciso di fare quello che ho fatto, perché immagino che sarebbe di aiuto (e fu chiesto, ovviamente).

Il centro del programma sono due database, uno per gli articoli e un altro per i caratteri. I caratteri devono avere una poszione temporanea di oggetti, ma tutti gli elementi devono poter essere elencati in qualsiasi momento.

Ho deciso di disporre di un arraylist di elementi, ogni elemento con un valore booleano disponibile o non disponibile (facilitando la visualizzazione di tutti gli elementi e gli elementi disponibili). Ogni personaggio avrebbe il proprio arraylist di oggetti più piccolo, al quale aggiungerei duplicati dell'articolo dal database.

Per poter accedere al database da altre classi (questo è il punto in cui ho iniziato con l'idea), ho considerato la mia opzione più semplice per rendere statico il grande arraylist perché non esiste alcuna situazione in cui io abbia bisogno di non esistere e non c'è nessuna situazione in cui ho bisogno di più di uno. Ovviamente, mentre creavo la lista statica, avevo bisogno di rendere statici anche tutti i metodi di base per interagire con esso.

Sono abbastanza sicuro che ci sono modi migliori per fare ciò che sto cercando di fare, ma sono solo un principiante che pratica.

EDIT2: Oh, e l'elenco di elementi verrà aggiunto a, rimosso da e gli elementi modificati durante l'esecuzione del programma. Un altro effetto dei personaggi che ricevono copie di oggetti è che i loro oggetti rimarranno gli stessi finché li avranno.

+3

modello Singleton? – Patashu

+3

Tutto in 'Math',' Objects', o 'Arrays' è statico, quindi non c'è nulla di intrinsecamente sbagliato in esso. Potresti provare a cercare il modello singleton e vedere se questo è quello che stai cercando – nullptr

+2

Singleton è spesso considerato un anti-pattern, qualcosa da cercare di evitare. –

risposta

2

Sulla base del vostro aggiornamento, siete arrivati ​​al classico "It's a singleton!" momento, dopo il quale qualcuno dovrebbe farti notare che "Non è (quasi) mai un singleton!". Invece, questa dovrebbe essere una classe normale, non statica, non singleton, e il resto dell'applicazione dovrebbe essere scritto in modo da utilizzare sempre una singola istanza di essa. Il fatto che la tua applicazione abbia bisogno solo di una singola istanza di una cosa non rende la cosa un singleton. Trarrai vantaggio dalla lettura di molti degli articoli pubblicati dalle ricerche di Google per "why is singleton evil" e "singleton antipattern".

Sembra anche che tu stia parlando di uno stato mutabile condiviso, che è un intero (enorme) potenziale di worm che non vuoi entrare senza un'attenta considerazione.

+0

Sì, sembra che ci sia un sacco di antipatia per la classe Singleton. Non posso dire di capire esattamente tutto, ma non vedo perché dovrei evitare una buona forma generalmente accettata. La cosa è, però, non sono sicuro di come andrei in giro usando una singola istanza. Non riuscivo a capire come creare un metodo nella classe Character per prendere un Item dall'elenco degli oggetti, perché Java non mi permetteva di eseguire iterazioni se l'elenco non fosse statico (inizialmente lo avevo costruito altrove). – Klaabu

+1

Qual è questa "buona forma" di cui parli? I singleton non sono una buona forma e nemmeno classi statiche. Per le istanze dei personaggi che hanno accesso alle informazioni sugli oggetti, avresti qualcosa che garantisce che tutti i personaggi abbiano un oggetto appropriato su cui lavorare. Questo ti indirizza verso l'iniezione di dipendenza, che ha un forte impatto sulla testabilità. Gli articoli sopra citati espongono su questi e altri punti in grande dettaglio. –

+1

Intendevo dire che evitare i singleton è una buona forma e mi piacerebbe farlo. – Klaabu

2

Mi spiace dirlo ma temo che il tuo possa essere un piano sbagliato e che potrebbe essere necessario riprogettare il programma. La tua classe ha uno stato e questo mi suggerisce che non dovrebbe essere statico.

cose che dovrebbero essere statico:

  • Costanti
  • metodi Utility
  • campi che appartengono alla classe e non l'istanza.

Considerare di fornirci ulteriori informazioni sulla struttura del programma in modo da poter fornire una risposta più precisa.

+0

Grazie per la risposta, aggiorno spiegando un po 'di più sul programma. Cosa intendi per "La tua classe ha uno stato"? – Klaabu

4

Se nel proprio sistema è necessaria esattamente una lista di Thing s, è necessario chiedersi quali sono queste cose. Sono elementi che possono essere configurati prima di ogni corsa? Sono cose che cambieranno mentre l'utente esegue il programma?Forse queste cose dovrebbero essere archiviate come record in un database, anche in una memoria leggera come Apache Derby o un database NoSQL.

Anche se si dispone effettivamente di un set di elementi fisso, è consigliabile utilizzare un sistema di distribuzione delle dipendenze e distribuire l'elenco in ambito Singleton anziché utilizzare un singleton cablato. In questo modo è possibile sostituire l'elenco nelle classi di test modificando la configurazione.

Se si trova l'ultima confusione, considerare questo invece. Supponiamo che tu abbia una classe che gestisce Things, ad esempio mantenendo un elenco statico di essi al suo interno. Qualcosa di simile:

public class ThingCatalog { 
    private static final List<Thing> things = new ArrayList<>(); 
    public ThingCatalog() { 
     // initialize list of things. 
    } 
    public List<Thing> getThings() { 
     return things; 
    } 
    public Thing getThingWithId(int id) { 
     // ... 
    } 
} 

Ora, si potrebbe fare ThingCatalog una classe Singleton; hai visto come si fa. Rendi privato il costruttore e crea un metodo statico getInstance. Si sarebbe tentati di scrivere

public class TreasureGenerator { 
    private ThingCatalog things = ThingCatalog.getInstance(); 
    // ... 
} 

Che cosa succede se si desidera scrivere unit test per il metodo in questa classe che non utilizzano le cose? Non hai bisogno delle cose, quindi non hai proprio bisogno di ThingCatalog. Unforunately, sei bloccato con esso.

È possibile iniziare a risolvere il problema dando TreasureGenerator un metodo setThingCatalog:

public void setThingCatalog(ThingCatalog things) { 
    this.things = things; 
} 

Naturalmente, avete un solo ThingCatalog, in modo che non aiuta molto. Ma se si ha un'interfaccia che ThingCatalog potrebbe attuare:

public interface ThingVendor { 
    List<Thing> getThings(); 
    Thing getThingById(int id); 
} 

e tutte le classi utilizzate ThingVendor invece di ThingCatalog, si potrebbe sostituirlo nei test.

Ecco un esempio più aziendale. Stai scrivendo un programma finanziario e devi stampare la data di oggi sugli assegni. Tipico è scrivere codice come:

String recipient = ...; 
String accountOwner = ...; 
BigDecimal amount = ...; 
String accountNumber = ...; 
Date today = new Date(); 
printCheck(...); 

Ora, qualcuno ti chiede "Il tuo programma può gestire correttamente i giorni bisestili?" Quattordici anni fa, la domanda avrebbe potuto essere su Y2K. Come lo verificheresti? Sei bloccato con oggi in questo metodo.

Invece, si scrive un'interfaccia chiamata DateGenerator:

public interface DateGenerator { 
    Date today(); 
} 

public class TodayGenerator implements DateGenerator { 
    public Date today() { return new Date(); } 
} 

public class LeapDayGenerator implements DateGenerator { 
    public Date today() { 
     Calendar cal = Calendar.getInstance(); 
     cal.set(2016, FEBRUARY, 29); // assume static imports; 
     return cal.getTime(); 
    } 
} 

La classe dovrebbe avere un metodo setDateGenerator, e devi usare TodayGenerator normalmente. Nel tuo test del giorno bisestile, dovresti utilizzare il LeapDayGenerator.

Un sistema di iniezione di dipendenza automatizza questi processi. Quello che imparerai con l'esperienza se stai con l'informatica è che gli oggetti non dovrebbero sapere come configurarsi. Altre parti del progetto dovrebbero incollare oggetti insieme.

+0

Volevo fare tutto in Java per la pratica, anche se mi sono reso conto molto rapidamente che molte cose sarebbero state molto più semplici con SQL. Gli elementi stessi non sono corretti (l'elenco può essere aggiunto e rimosso durante l'esecuzione del programma). Mi dispiace, ma come principiante, "un sistema di iniezione delle dipendenze e la distribuzione della lista in ambito singleton invece di usare un singleton hardwired" suona come technobabble. : P Ho appena saputo che cosa è un singleton in questa stessa discussione. – Klaabu

+1

Mi spiace - a volte giudico male il livello dello scrittore. Modificherò il mio post per fare un suggerimento più appropriato. –

+0

Oh wow, questa è una bella modifica carnosa, ottima roba per quello che sto cercando di fare; molte grazie! – Klaabu

1

Sono incline a concordare sul fatto che il design non sia ottimale. Molti dei tuoi obiettivi sembrano essere quelli tipici della programmazione procedurale, piuttosto che orientata agli oggetti.

Se si scopre che il proprio progetto ha una forte dipendenza da dati statici modificabili, è necessario chiedersi perché sono necessari così tanti dati globali.

Problemi correlati