Uma classe estática com um monte de variáveis estáticas é meio que um hack.
/**
* Grotty static semaphore
**/
public static class Ugly {
private static int count;
public synchronized static void increment(){
count++;
}
public synchronized static void decrement(){
count--;
if( count<0 ) {
count=0;
}
}
public synchronized static boolean isClear(){
return count==0;
}
}
Um singleton com uma instância real é melhor.
/**
* Grotty static semaphore
**/
public static class LessUgly {
private static LessUgly instance;
private int count;
private LessUgly(){
}
public static synchronized getInstance(){
if( instance==null){
instance = new LessUgly();
}
return instance;
}
public synchronized void increment(){
count++;
}
public synchronized void decrement(){
count--;
if( count<0 ) {
count=0;
}
}
public synchronized boolean isClear(){
return count==0;
}
}
O estado é APENAS na instância.
Portanto, o singleton pode ser modificado posteriormente para fazer pooling, instâncias locais de thread, etc. E nenhum código já escrito precisa ser alterado para obter o benefício.
public static class LessUgly {
private static Hashtable<String,LessUgly> session;
private static FIFO<LessUgly> freePool = new FIFO<LessUgly>();
private static final POOL_SIZE=5;
private int count;
private LessUgly(){
}
public static synchronized getInstance(){
if( session==null){
session = new Hashtable<String,LessUgly>(POOL_SIZE);
for( int i=0; i < POOL_SIZE; i++){
LessUgly instance = new LessUgly();
freePool.add( instance)
}
}
LessUgly instance = session.get( Session.getSessionID());
if( instance == null){
instance = freePool.read();
}
if( instance==null){
// TODO search sessions for expired ones. Return spares to the freePool.
//FIXME took too long to write example in blog editor.
}
return instance;
}
É possível fazer algo semelhante com uma classe estática, mas haverá sobrecarga por chamada no despacho indireto.
Você pode obter a instância e passá-la para uma função como um argumento. Isso permite que o código seja direcionado para o singleton "certo". Sabemos que você só precisará de um deles ... até não precisar.
O grande benefício é que singletons com estado podem se tornar thread-safe, enquanto uma classe estática não pode, a menos que você a modifique para ser um singleton secreto.