2010-06-26 8 views
6

Questo potrebbe sembrare un'idea bizzarra e non ho ancora pensato bene.Generare singoletti

Supponiamo di avere un'applicazione che richiede un certo numero di singleton per eseguire alcuni I/O, ad esempio. Potresti scrivere un singleton e fondamentalmente riprodurre il codice tutte le volte che è necessario.

Tuttavia, come programmatori dovremmo inventare soluzioni inventive che evitino ridondanza o ripetizione di qualsiasi tipo. Quale sarebbe una soluzione per rendere più qualcosa che potrebbe agire come un singleton.

P.S: Questo è per un progetto in cui non è possibile utilizzare un framework come Spring.

+4

Più persone è in qualche modo contraddittorio con il termine di un singleton. Prendi in considerazione l'utilizzo del modello di fabbrica. – Andreas

+0

Singletons per definizione hanno una singola istanza nel processo. Quindi quando dici più singleton, intendi A. Istanze multiple dello stesso oggetto? B. Un codice generico per classi di singleton diverse da utilizzare per limitare ciascuna di esse a una singola istanza –

+1

Poiché si sta parlando di Spring, si sta utilizzando un'applicazione web JSP/Servlet? Hai considerato 'ServletContextListener'? Singletons in un webapp odora. – BalusC

risposta

3

Si potrebbe introdurre un'astrazione come questo:

public abstract class Singleton<T> { 
    private T object; 

    public synchronized T get() { 
    if (object == null) { 
     object = create(); 
    } 
    return object; 
    } 

    protected abstract T create(); 
} 

Poi per ogni Singleton, è solo bisogno di scrivere questo:

public final Singleton<Database> database = new Singleton<Database>() { 
    @Override 
    protected Database create() { 
    // connect to the database, return the Database instance 
    } 
}; 

public final Singleton<LogCluster> logs = new Singleton<LogCluster>() { 
    ... 

Quindi è possibile utilizzare i single scrivendo database.get(). Se il singleton non è stato creato, viene creato e inizializzato.

La gente di motivo probabilmente non fanno questo, e preferiscono semplicemente più volte scrivere qualcosa di simile:

private Database database; 

public synchronized Database getDatabase() { 
    if (database == null) { 
    // connect to the database, assign the database field 
    } 
    return database; 
} 

private LogCluster logs; 

public synchronized LogCluster getLogs() { 
    ... 

è perché alla fine è solo un altro riga di codice per ogni Singleton, e la possibilità di sbagliare il modello initialize-singleton è piuttosto bassa.

+3

Questo è ... spaventoso. Collegamento del DB durante la costruzione di un Singleton? – BalusC

+3

Questa è una complicazione eccessiva al massimo qui. –

+1

@Gnarly fondamentalmente sto sostenendo che questo è il motivo per cui tu * non * fai questo. Personalmente preferisco Guice (anche se può essere complicato a modo suo.) –

1

Come passare un parametro alla funzione che crea il singleton (ad esempio, il nome o la specializzazione), che sa creare un singleton per ogni parametro univoco?

+0

Sarebbe l'ideale. Questo va di pari passo con il suggerimento di usare un modello di fabbrica. –

2

Esiste uno schema multiton. Indipendentemente da ciò, sono sicuro al 60% che la vera soluzione al problema originale sia un RDBMS.

+0

+1 per Multiton Pattern –

+0

Non avevo ancora sentito parlare di questo pattern e sembra molto simile a quello che Spring deve fare internamente. Ecco un link per riferimento futuro: http://j2eeblogger.blogspot.com/2007/10/singleton-vs-multiton-synchronization.html –

-1

So che hai chiesto di Java, ma qui è una soluzione in PHP come esempio:

abstract class Singleton 
{ 
    protected function __construct() 
    { 
    } 

    final public static function getInstance() 
    { 
     static $instances = array(); 

     $calledClass = get_called_class(); 

     if (!isset($instances[$calledClass])) 
     { 
      $instances[$calledClass] = new $calledClass(); 
     } 

     return $instances[$calledClass]; 
    } 

    final private function __clone() 
    { 
    } 
} 

Poi basta scrivere:

class Database extends Singleton {} 
+0

-1 - Questo approccio non funziona per Java. I metodi statici non sono ereditati, quindi non esiste l'equivalente di 'get_called_class'. –

+0

Questo è corretto, ma dato che sono interessato anche a PHP, ti scongiuro perché ti sei preso la briga di pubblicare un esempio di codice. –

3

Tuttavia, come i programmatori siamo si suppone che creino soluzioni inventive che evitino ridondanze o ripetizioni di qualsiasi tipo.

Non è corretto. Come programmatori, dovremmo proporre soluzioni che soddisfino i seguenti criteri:

  • soddisfare i requisiti funzionali; per esempio. eseguire come richiesto senza errori,
  • sono consegnati entro il termine previsto,
  • sono mantenibili; per esempio. il prossimo sviluppatore può leggere e modificare il codice,
  • esegue abbastanza velocemente per l'attività in mano e
  • può essere riutilizzato in attività future.

(Questi criteri sono più o meno ordinate per priorità decrescente, anche se diversi contesti possono dettare un ordine diverso.)

Inventiva non è un requisito, e "evitare [ing] la ridondanza o la ripetizione di ogni tipo" non lo è neanche. In effetti, entrambi possono essere decisamente dannosi ... se il programmatore ignora i criteri reali.

Riportare questo alla tua domanda. Dovresti solo cercare modi alternativi di fare singleton se renderà il codice più gestibile. Le soluzioni "inventive" complicate possono benissimo tornare al morso (o alle persone che devono mantenere il proprio codice in futuro), anche se riescono a ridurre il numero di righe di codice ripetuto.

E come altri hanno sottolineato (ad esempio @BalusC), il pensiero corrente è che il modello singleton deve essere evitato in molte classi di applicazione.

+0

Ho già visto molti refusi del mio nome, ma non ancora questo :) – BalusC

+0

@BalusC - Risolto. Scusate. –

+0

Da un lato, se questo ha risposto alla domanda, avrei votato.D'altra parte, sembra una risposta argomentativa a un commento non necessario nel post originale (sebbene il pensiero errato dei PO possa benissimo essere la causa alla radice di questa domanda). –

2

@BalusC ha ragione, ma lo dirò più forte, i singleton sono cattivi in ​​tutti i contesti. Webapp, app desktop, ecc. Semplicemente non farlo.

Tutto un singleton è in realtà un insieme di dati globali. I dati globali sono cattivi. Rende impossibile il corretto test dell'unità. Rende molto più difficile rintracciare bug strani.

Il libro della Gang of Four è completamente sbagliato. O almeno obsoleto di un decennio e mezzo.

Se si desidera una sola istanza, avere una fabbrica che ne faccia una sola. È facile.