Newsgroup: it.comp.java
Titolo: chiarimento su singleton

Ciao, ho un dubbio circa l'uso del singleton pattern.
Ho una classe singleton cosi implementata:
class MySingleton{
	private MySingleton() {
     	}
	static class SingletonHolder {
	  static MySingleton instance = new MySingleton();
     	}
	public static MySingleton getInstance() {
           return SingletonHolder.instance;
     	}	
	public void doSomething(){}
}
Ho copiato l'implementazione del singleton fatta cosi, cioè con l'uso di 
una inner class static, da un blog dove veniva presentata questa 
soluzione come migliore delle varie implementazioni con metodo 
synchronized (anche se ad essere sincero, non ho capito perfettamente in 
cosa è migliore).
La domanda comunque è questa:
con le classi in singleton, cosa succede rispetto al Garbage Collector?
Mi spiego meglio:
class Main{
    public static void main(String[] args){
	method_A();
	method_B();
    }
    public void method_A(){
      MySingleton.getInstance().doSemothing();
    }
    public void method_B(){
      MySingleton.getInstance().doSemothing();
    }
}
Visto che non mantengo da nessuna parte un puntatore all'istanza di 
MySingleton, ne viene creata una nuova ad ogni chiamata? Oppure è sempre 
la stessa?
Grazie a chiunque vorrà chiarirmi il dubbio!
matteo

 la stessa?
E sempre la stessa.
L'istanza non viene mai raccolta (collected) dal garbage collector 
perché c'e' sempre almeno il campo SingletonHolder.instance che mantiene 
il riferimento (o puntatore) all'instanza.
-- 
Andrea Francia
http://andreafrancia.blogspot.com/2008/06/macross-frontier.html

 il riferimento (o puntatore) all'instanza.
Ok, quindi come faccio a liberarmene? Oppure non c'è modo e l'istanza 
"muore" solo quando esco dal programma?
grazie per la risposta,
matteo

Ciao, ho un dubbio circa l'uso del singleton pattern.
Posso chiederti perché vuoi usare un singleton? (il singleton non č
tra i pattern piů amati, tra gli esperti; č quasi un antipattern :-)

 la stessa?
MySingleton non è una istanza.
-- 
 Fino all'anno scorso avevo un solo difetto. Ero presuntuoso.
http://softvalley.blogspot.com
http://www.flickr.com/photos/marko_po/

 "muore" solo quando esco dal programma?
hai voglia se c'è modo, basta non creare un singleton.
ti sei chiesto il perchè di tutto quel popò di codice quando per 
istanziare un oggetto come vuoi tu basta una semplice new?


 "muore" solo quando esco dal programma?
Di solito non ha senso liberarsi del singleton.
Di solito un oggetto solo non occupa molta memoria.
Di solito il singleton ti serve per tutta la durata dell'applicazione.
Se vuoi liberartene metti il MySingleton.SingletonHolder.instance a 
null. Se non c'e' nessun'altro riferimento il GC (se e quando vuole) 
libererà la memoria.
L'allocazione avviene nella riga 	
	static MySingleton instance = new MySingleton();
Questa riga viene eseguita appena dopo che la classe 
MySingleton.SingletonHolder viene caricata.


 
rootkit, non mi piacciono per niente , ma proprio per niente i tuoi toni 
  polemici e saccenti.
tra l'altro, mi sembra che capisci poco l'italiano.
un puntatore all'istanza di MySingleton NON significa in nessun modo che 
MySingleton è un'istanza. fai un po' di analisi logica della frase e 
capirai il perchè.
 >hai voglia se c'è modo, basta non creare un singleton.
 >ti sei chiesto il perchè di tutto quel popò di codice quando per 
 >istanziare un oggetto come vuoi tu basta una semplice new?
ma che ne sai di cosa voglio io? ma pensa che modi! come se fossi un idiota.
certo che la maleducazione della gente è sempre senza confini.

Andrea Laforgia ha scritto:

Sto scrivendo un'applicazione in JavaME e ho una classe che implementa 
una sorta di Cache, a cui accedono quasi tutte le altre classi, in 
particolare quelle che rappresentano le View del MVC. Ho scelto il 
singleton perchč di Cache ne esiste solo una, condivisa tra tutti e non 
sono riuscito a trovare una collocazione precisa tra le varie classi.
Comunque, i consigli sono ben accetti! Con quali altri pattern potrei 
sostituire il singleton in questo caso?
Grazie,
ciao
Matteo

 sostituire il singleton in questo caso?
Dependency Injection
In questo modo la classe che utilizza la Cache funzionerà anche in 
un'ambiente dove per ottenere la Cache non si deve fare
	Cache.getInstance();


 
In piu' questo ti permetterebbe semplificherebbe il testing, perché 
durante il testing potresti iniettargli al posto della solita Cache un 
Mock Object da usare per verificare come la classe interagisce con la Cache.


 certo che la maleducazione della gente è sempre senza confini.
per quello che puo' valere,sono completamente d'accordo con te.
Ma come diceva il vate "...non ti curar di lor ma guarda e passa..."
-- 
ac
y-1=x

 ma che ne sai di cosa voglio io? 
prima di tutto ti chiedo scusa per aver travisato il messaggio di cui 
sopra e con questo ho la coscienza a posto.
adesso ti rispondo a questa domanda: no, non lo so cosa vuoi te, 
soprattutto perchè non lo sai nemmeno tu. e non che ti sto offendendo, 
ti sto dicendo semplicemente le cose come stanno senza girarci intorno.
il singleton è un design pattern che si implementa per garantire che di 
quel tipo tu abbia una e una sola istanza. se in qualche modo 
consentisse di dereferenziare quell'unica istanza, è evidente che non 
sarebbe più un singleton. quel codice che hai postato (fra l'altro si 
trovano facilmente esempi migliori, 
http://it.wikipedia.org/wiki/Singleton
) serve esattamente a questo.


 Cache.
L'ho proprio appena letto! uno dei vantaggi del pattern è appunto nel 
testing.
Ma quindi, in ogni classe "interessata" alla Cache, dovrei implementare 
un metodo (magari implementando la stessa interfaccia) del tipo
public void setCache(Cache cacheInstance)
corretto?
ultimo dubbio, a chi spetta il compito di crearla per la prima volta, e 
quindi "iniettare" l'istanza nelle varie classi?
non c'è il rischio così facendo di creare delle dipendenze tra classi 
che, adottando invece il singleton, non avrebbero niente a che fare 
l'una con l'altra (ognuna accede alla Cache senza aspettare di riceverne 
    il riferimento)
grazie,
matteo

 sono riuscito a trovare una collocazione precisa tra le varie classi.
dai sempre un'occhiata alle librerie commons prima di inventare qualcosa:
http://commons.apache.org/pool/
un object pooling potrebbe essere la tua cache? la butto lì.


 evidente che non sarebbe più un singleton.
?!
forse stai usando la parola "dereference" in modo impreciso...
il "dereferencing" e' l'atto di accedere al valore, non l'atto di fare 
puntare il reference a qualche altro oggetto.
Quote da wikipedia:
"In computer science, a reference is an object containing information which 
refers to data stored elsewhere, as opposed to containing the data itself. 
Accessing the value referred to by a reference is called dereferencing it"
Forse ti ho frainteso?!
Tommy 

 
http://it.wikipedia.org/wiki/Singleton
) serve esattamente a questo.
Si trovano facilmente dei migliori! Grazie davvero. Tant'è che riporto 
il codice trovato sul tuo prezioso link:
public class Singleton {
   // private: non viene generato un costruttore pubblico
   private Singleton() {}
   /**
    * La classe Contenitore viene caricata alla prima esecuzione del 
getInstance()
    * o al primo accesso a Contenitore.ISTANZA, non prima, e in modo 
serializzato
    */
   private static class Contenitore {
     private final static Singleton ISTANZA = new Singleton();
   }
   public static Singleton getInstance() {
     return Contenitore.ISTANZA;
   }
}
Mi sembra vagamente IDENTICO a quello che ho postato io (a meno dei 
modificatori final, che provvero' ad aggiungere).
Matteo.

 forse stai usando la parola "dereference" in modo impreciso...
sicuramente. è una cazzata, intendevo dire in modo molto bovino perdere 
il riferimento a quell'istanza.
scusasse...


 
http://it.wikipedia.org/wiki/Singleton
) serve esattamente a questo.
Si trovano facilmente dei migliori! Grazie davvero. Tant'è che riporto


 modificatori final, che provvero' ad aggiungere).
mancava sia il final che il private.
ora capisciammè, non prenderla come un flame, ma purtroppo sono errori.


l'una con l'altra
Che dipendenze vedi?

 
ma per favore.

 
Andrea, che non si è ancora scusato per avermi messo in bocca parole che 
non ho detto, ha ragione.
La dependency injection via costruttore è comoda perché di permette di 
essere sicuro che inizializzi solo una volta. Di solito io uso il 
seguente pattern:
public class Pippo {
   final Cache cache;
   public Pippo(Cache cache, altro ... ) {
     // altro ...
     this.cache = cache;


FONDAMENTALE. E per questo ho chiesto delucidazioni.
Il mio personale consiglio è quello di non usare il singleton.
Scrivi una semplice classe e passane un'istanza a chi di dovere.
Tieni presente che, in generale, nella programmazione orientata agli
oggetti molte preoccupazioni sono pure e semplici paranoie dei
programmatori. Se tu stabilisci che un'istanza dovrà essere istanziata
una ed una sola volta, non hai necessariamente bisogno di forzare
questo contratto, materialmente, aggiungendo codice. E' un vincolo e
basta. Lo dichiari e lasci la strada aperta al programmatore. 
A volte è anche meglio.

non ho detto, ha ragione.
Non credo proprio di dovermi scusare con te. Ho la coscienza a posto.
Se ti riferisci a qualche altro thread, ho ignorato da un pezzo le
risposte.

testing.
...che è ciò che alla fine dovrebbe guidare lo sviluppo ;-)


Per due volte di seguito mi hai accusato di dire una frase che non ho 
detto senza neanche prenderti la briga di controllare se non ti eri 
sbagliato a leggere.


sbagliato a leggere.
Per cortesia, non alimentare polemiche sterili.

>> una semplice new?
ecco un esempio un tantino piu' complesso:
public enum MySingleton {
  // Single instance:
  instance;
  // Member variables:
  private final List<String> listOfString;
  // Constructor:
  MySingleton()
  {
      listOfString = new ArrayList<String>();
  }
  // Methods:
  synchronized void addString(final String str)
  {
      listOfString.add(str);
  }
}
Anche se questo esempio non ha senso, ci ho messo cmq  un esempio di member 
variable, un esempio di constructor ed un esempio di metodo. Ho reso il 
metodo synchronized in quanto il singleton puo' essere facilmente usato da 
piu' threads.
Per usare MySingleton, invece di fare:
MySingleton.getInstance().addString("Hello");
si fa:
MySingleton.instance.addString("Hello");
Tommy


Mi stai dicendo che non consideri neanche una remota possibilità di 
esserti sbagliato e quindi non hai bisogno di andare a controllare per 
essere a posto con la coscienza?



Il Test Driven Development non è *il* modo di fare software ma è *un* 
modo di fare software.
Io personalmente lo prediligo, ma non è che bisogna seguirlo per forza.


Io personalmente lo prediligo, ma non è che bisogna seguirlo per forza.
Stai calmo, non ti agitare, rilassati. Non ho tirato fuori il
test-driven development. Ho semplicemente esposto un concetto generale
e cioè che l'attività di testing è talmente fondamentale da segnare
una linea guida quando si scrive software. Poi segui l'approccio che
più ti aggrada. E' fuor di dubbio che oggi, il testing, è un'attività
di importanza primaria. Progettare i test PRIMA di scrivere il codice,
porta a scrivere codice migliore. E' spesso difficile e difficilmente
conciliabile con certi contesti lavorativi, ma se po' fa.

 test-driven development. 
Ma sě che l'hai tirato fuori:
   test -> test
   guidare -> drive
   sviluppo -> development
Quello che hai affermato č il principio del TDD.


Ma sě che l'hai tirato fuori:
No, hai palesemente frainteso e non perderň ulteriore tempo a
spiegarti il perché.


Perché no?
