Eu estava lendo o artigo de Singleton na Wikipedia e me deparei com este exemplo:
public class Singleton {
// Private constructor prevents instantiation from other classes
private Singleton() {}
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
Embora eu realmente goste da maneira como esse Singleton se comporta, não consigo ver como adaptá-lo para incorporar argumentos ao construtor. Qual é a maneira preferida de fazer isso em Java? Eu teria que fazer algo assim?
public class Singleton
{
private static Singleton singleton = null;
private final int x;
private Singleton(int x) {
this.x = x;
}
public synchronized static Singleton getInstance(int x) {
if(singleton == null) singleton = new Singleton(x);
return singleton;
}
}
Obrigado!
Edit: Eu acho que comecei uma tempestade de controvérsia com o meu desejo de usar Singleton. Deixe-me explicar minha motivação e espero que alguém possa sugerir uma idéia melhor. Estou usando uma estrutura de computação em grade para executar tarefas em paralelo. Em geral, eu tenho algo parecido com isto:
// AbstractTask implements Serializable
public class Task extends AbstractTask
{
private final ReferenceToReallyBigObject object;
public Task(ReferenceToReallyBigObject object)
{
this.object = object;
}
public void run()
{
// Do some stuff with the object (which is immutable).
}
}
O que acontece é que, embora eu apenas passe uma referência aos meus dados para todas as tarefas, quando as tarefas são serializadas, os dados são copiados repetidamente. O que eu quero fazer é compartilhar o objeto entre todas as tarefas. Naturalmente, eu posso modificar a classe da seguinte maneira:
// AbstractTask implements Serializable
public class Task extends AbstractTask
{
private static ReferenceToReallyBigObject object = null;
private final String filePath;
public Task(String filePath)
{
this.filePath = filePath;
}
public void run()
{
synchronized(this)
{
if(object == null)
{
ObjectReader reader = new ObjectReader(filePath);
object = reader.read();
}
}
// Do some stuff with the object (which is immutable).
}
}
Como você pode ver, mesmo aqui, tenho o problema de que a passagem de um caminho de arquivo diferente não significa nada após a passagem do primeiro. É por isso que gosto da ideia de uma loja que foi postada nas respostas. De qualquer forma, em vez de incluir a lógica para carregar o arquivo no método run, eu queria abstrair essa lógica em uma classe Singleton. Não darei mais outro exemplo, mas espero que você entenda. Deixe-me ouvir suas idéias para uma maneira mais elegante de realizar o que estou tentando fazer. Mais uma vez obrigado!