Devo creare un singolo oggetto per una chiamata di metodo comune o utilizzare un approccio a distanza?

6

Sto creando un piccolo programma di combattimento rpg solo per divertimento e per praticare il mio java (sono un po 'nuovo hehe).

Ho una classe chiamata Dice con un metodo chiamato d20 che lancia un numero casuale compreso tra 1 e 20. Il metodo sarà usato frequentemente da tutte le altre classi nel programma.

La mia domanda è, dovrei creare una singola istanza della classe Dice nel mio metodo principale che può essere chiamata anche da tutte le altre classi. Funziona? Ha bisogno di essere dichiarato come una variabile di riferimento pubblica per funzionare? È solo una cattiva pratica?

Dovrei invece rendere statico il metodo in modo che non sia necessario creare un'istanza dell'oggetto?

O dovrei creare l'oggetto quando la chiamata deve essere fatta e poi buttarla via dopo usando la garbage collection?

Non sono sicuro che il primo modo funzioni. Gli ultimi due non so quale sia una buona pratica.

La mia motivazione principale qui è capire quale sia la migliore pratica e perché.

    
posta Flyte 79 09.01.2015 - 16:06
fonte

5 risposte

2

Qualunque classe che richiede un'origine di numeri casuali accetta un Function<Integer, Integer> (o qualsiasi altra interfaccia funzionale equivalente che ti piace) nel suo costruttore.

Crea un metodo statico int rollDie(int sides) che genera un numero casuale da 0 a sides , incluso. Questo evita la ridondanza di rollD20 , rollD8 , ecc. Interamente questo probabilmente sarà solo una chiamata a Random.nextInt(sides + 1) .

È possibile passare il metodo statico a qualsiasi classe che lo richiede utilizzando un riferimento al metodo:

new Character(Dice::rollDie)

Per il test delle unità, puoi facilmente sostituire rollDie con una funzione prevedibile:

new Character(sides -> 5);

Questo equivale all'approccio di Valenterry ma con un numero minore di regole e possibilmente più efficiente, se il compilatore / macchina virtuale può utilizzare il fatto che il lambda si riferisce a un metodo statico. È anche un po 'più facile da riutilizzare, dal momento che rollDie funziona con qualsiasi interfaccia contenente un metodo che prende un Integer e restituisce un Integer , quindi puoi usarlo anche in altri contesti.

    
risposta data 09.01.2015 - 17:24
fonte
5

Quando il metodo non ricorda uno stato, un Mehtod statico dovrebbe essere a posto. Anche il metodo del numero casuale di stenografia di java nella classe Math ( Math.random() ) è un metodo statico.

    
risposta data 09.01.2015 - 16:20
fonte
5

Per prima cosa, non chiamerei la classe Dice . Piuttosto chiamalo DiceShaker o giù di lì e dagli un metodo in modo da poter chiamare diceShaker.roll1W20() o anche meglio, creare diversi DadiShakers (per composizione / estensione) per scopi diversi e creare DiceShaker un'interfaccia.

Successivamente, sì, è positivo se crei una singola istanza che passi a tutte le classi che hanno bisogno di un DiceShaker . In questo modo, puoi facilmente testare se il DiceShaker funziona correttamente nei test unitari. Puoi anche dare ai tuoi corsi speciali DiceShaker che possono ad es. essere più performante per i casi limite.

per esempio:.

public class Fighter {
    private DiceShaker diceShaker
    public Fighter(DiceShaker diceShaker) { this.diceShaker = diceShaker }
    public tryAttack(Fighter target) { if(diceShaker.roll1W20() > 10) this.attack(target) }
}

(nota che la logica per attaccare o non attaccare non dovrebbe essere nella classe Fighter come sopra. Questo è solo per semplificare questo esempio.)

Non renderlo statico. Sarà quindi difficile testare il tuo diceShaker o fornire funzionalità diverse per classi diverse in seguito o in fase di esecuzione. Gli stessi inconvenienti ci sono se crei il DiceShaker nel momento in cui ne hai bisogno e lo scarti dopo. Questo è l'opposto di Iniezione delle dipendenze .

Anche se molte java libs usano funzioni statiche, il più delle volte non è una buona pratica o solo una soluzione per altri difetti nel linguaggio java (come apache.commons.io.FileUtils )

    
risposta data 09.01.2015 - 16:41
fonte
1

Direi che dovresti inizializzare solo un oggetto d20 per la tua applicazione.

L'ispirazione per questo stile è che un DM di vita reale ha solo una D20. Non ha una scatola intera dove ne tira fuori una, la tira e la getta via.

Non devi assegnare una proprietà dadi ai tuoi personaggi RPG semplicemente perché i personaggi RPG non tirano i dadi, come fa il dungeonmaster.

Quindi un metodo statico come GetD20Roll (): Number è il più chiaro. Non suggerisce che il mostro stesso stia rotolando i dadi.

    
risposta data 09.01.2015 - 21:40
fonte
-1

Ho seguito il codice, quindi ho potuto misurare il tempo in entrambe le opzioni.

public static void multiple() {
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100_000_000; i++) {
        Instance instance = new Instance();
        instance.rand();
    }
    long end = System.currentTimeMillis();
    long time = end - start;
    System.out.println("Multiple instance time: " + time);
}

public static void single() {
    long start = System.currentTimeMillis();
    Instance instance = new Instance();
    for (int i = 0; i < 100_000_000; i++) {
        instance.rand();
    }
    long end = System.currentTimeMillis();
    long time = end - start;
    System.out.println("Single instance time: " + time);
}

public static void statc() {
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100_000_000; i++) {
        StaticInstance.rand();
    }
    long end = System.currentTimeMillis();
    long time = end - start;
    System.out.println("Static instance time: " + time);
}

Dopo aver eseguito 100.000.000 di tempo. Il risultato è stato:

Multiple instance time: 2879
Single instance time: 2714
Static instance time: 2770

Come previsto, più istanze sono l'opzione peggiore. È importante che nei miei campioni, il costruttore fosse stupido e leggero. Se hai un costruttore pesante, sarà un grosso problema per le prestazioni a più istanze.

La singola istanza era la migliore. Ma devi avere un riferimento all'istanza.

Statico era un po 'peggio di una singola istanza.

Cordiali saluti, Felipe

    
risposta data 10.01.2015 - 01:04
fonte

Leggi altre domande sui tag