Czytałem artykuł Singletona na Wikipedii i trafiłem na taki przykład:
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;
}
}
Chociaż bardzo podoba mi się sposób, w jaki zachowuje się ten Singleton, nie widzę, jak dostosować go do włączenia argumentów do konstruktora. Jaki jest preferowany sposób zrobienia tego w Javie? Czy musiałbym zrobić coś takiego?
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;
}
}
Dzięki!
Edycja: Myślę, że zacząłem burzę kontrowersji z moim pragnieniem użycia Singletona. Pozwólcie, że wyjaśnię moją motywację i mam nadzieję, że ktoś zasugeruje lepszy pomysł. Do równoległego wykonywania zadań używam struktury grid computing. Ogólnie mam coś takiego:
// 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).
}
}
Dzieje się tak, że nawet jeśli przekazuję tylko odniesienie do moich danych do wszystkich zadań, kiedy zadania są serializowane, dane są kopiowane w kółko. Chcę udostępnić obiekt wszystkim zadaniom. Oczywiście mógłbym zmodyfikować klasę w następujący sposób:
// 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).
}
}
Jak widać, nawet tutaj mam problem z tym, że przekazanie innej ścieżki do pliku nic nie znaczy po przejściu pierwszego. Dlatego podoba mi się pomysł na sklep, który został zamieszczony w odpowiedziach. W każdym razie zamiast włączać logikę do ładowania pliku w metodzie run, chciałem wyabstrahować tę logikę do klasy Singleton. Nie podam kolejnego przykładu, ale mam nadzieję, że zrozumiesz pomysł. Proszę, pozwól mi wysłuchać twoich pomysłów na bardziej elegancki sposób realizacji tego, co próbuję zrobić. Jeszcze raz dziękuję!