Come cambiare lo stato di un singleton in runtime

0

Considero che scriverò un semplice logger basato su file AppLogger da utilizzare nelle mie app, idealmente dovrebbe essere un singleton, quindi posso chiamarlo tramite

public class AppLogger {
    public static String file = "..";

    public void logToFile() {
        // Write to file
    }

    public static log(String s) {
        AppLogger.getInstance().logToFile(s);
    }
}

E per usarlo

AppLogger::log("This is a log statement");

Il problema è, qual è il momento migliore in cui dovrei fornire il valore del file poiché è solo un singleton?

Oppure come rifattorizzare il codice precedente (o saltare usando singleton) in modo che possa personalizzare il percorso del file di log? (Supponiamo che non abbia bisogno di scrivere su più allo stesso tempo)

P.S. So che posso usare la biblioteca, ad es. log4j, ma considera che è solo una domanda di progettazione, come rifattorizzare il codice sopra?

    
posta user34401 19.08.2014 - 09:10
fonte

3 risposte

2

Penso che potresti andare avanti e fornire un metodo setter per il percorso del file in AppLogger. Se stai utilizzando più thread nell'applicazione, assicurati di mantenere i metodi sincronizzati, poiché Singleton è un oggetto condiviso a cui è possibile accedere da tutti i thread:

public static void synchronized setFile(String filePath) {...}

public static void synchronized log(String s) {...}

Alcuni altri punti:

  • AppLogger::log non è corretta sintassi Java
  • Hai due metodi per la registrazione e entrambi sono public . Crea logToFile private e aggiungi un argomento stringa
  • Il riferimento al singolo singleton manca nella tua classe
  • La firma del log (String) non è corretta. Devi aggiungere un tipo di reso (come ho fatto io)
risposta data 19.08.2014 - 09:23
fonte
0

Consentendo al file di cambiare in qualsiasi momento, vengono visualizzati numerosi contrassegni rossi, ad esempio i principali problemi di sincronizzazione.

Ma, ancora peggio, cosa succede se il thread A registra allegramente 4 righe di

64.242.88.10 - - [07/Mar/2004:16:05:49 -0800] INFO:blah
INFO: Opening some connection to foo.bar.com
INFO: Connection established with 123.45.67.8
ERROR: Connection refused by socket 5432, bad credentials

e tra le righe 1 e 2 (o forse al centro di esse a seconda della granularità) La Discussione B chiama setFile(someCompletelyDifferentFile) ? Anche se synchronize di scrittura per riga, questo sarà un disastro.

Il tuo logger dovrebbe essere configurato in anticipo, preferibilmente all'avvio dell'applicazione, prima che qualcuno inizi a usarlo, e quindi non cambi i file in midstream.

    
risposta data 19.08.2014 - 18:23
fonte
0

Dipende se il nome del file è dinamico e può cambiare in qualsiasi momento o se il nome del file è impostato al momento dell'inizializzazione.

Se desideri un'inizializzazione una tantum, devi impostare il nome file nel codice di inizializzazione dell'app. Ignora qualsiasi chiamata a logToFIle prima che il nome del file sia stato impostato.

Oppure puoi impostare il nome del file nel costruttore o in getInstance (). Il singleton dovrebbe quindi essere in grado di inizializzarsi recuperando il nome del file da un file di configurazione.

Dall'altro lato, se il nome del file può cambiare durante l'esecuzione dell'app, devi gestirlo come qualsiasi altro stato mutabile. Accedere al singleton da getInstance () e chiamare il metodo setFilename ().

In ogni caso, se l'accesso a thread multipli è una possibilità, tutte le operazioni devono essere sincronizzate. Se si sta registrando, la scrittura del file di log richiederà molto più tempo della sincronizzazione.

    
risposta data 21.08.2014 - 23:23
fonte