I was reading the Singleton article on Wikipedia and I came across this example:
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;
}
}
While I really like the way this Singleton behaves, I can't see how to adapt it to incorporate arguments to the constructor. What is the preferred way to do this in Java? Would I have to do something like this?
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;
}
}
Thanks!
Edit: I think I have started a storm of controversy with my desire to use Singleton. Let me explain my motivation and hopefully someone can suggest a better idea. I am using a grid computing framework to execute tasks in parallel. In general, I have something like this:
// 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).
}
}
What happens is that even though I merely pass a reference to my data to all of the tasks, when the tasks are serialized, the data gets copied over and over. What I want to do is share the object among all of the tasks. Naturally, I might modify the class like so:
// 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).
}
}
As you can see, even here I have the issue that passing a different file path means nothing after the first one is passed. This is why I like the idea for a store which was posted in the answers. Anyhow, rather than including the logic for loading the file in the run method, I wanted to abstract this logic into a Singleton class. I will not provide yet another example, but I hope you get the idea. Please let me hear your ideas for a more elegant way to accomplish what I am trying to do. Thank you again!
"A singleton with parameters is not a singleton" statement is not completely correct. We need to analyze this from the application perspective rather than from the code perspective.
We build singleton class to create a single instance of an object in one application run. By having a constructor with parameter, you can build flexibility into your code to change some attributes of your singleton object every time you run you application. This is not a violation of Singleton pattern. It looks like a violation if you see this from code perspective.
Design Patterns are there to help us write flexible and extendable code, not to hinder us writing good code.
You can add a configurable initialization method in order to separate instantiation from getting.
Then you can call
Singleton.init(123)
once to configure it, for example in your app startup.Surprised that no one mentioned how a logger is created/retrieved. For example, below shows how Log4J logger is retrieved.
There are some levels of indirections, but the key part is below method which pretty much tells everything about how it works. It uses a hash table to store the exiting loggers and the key is derived from name. If the logger doesn't exist for a give name, it uses a factory to create the logger and then adds it to the hash table.
I think this is a common problem. Separating the "initialization" of the singleton from the "get" of the singleton might work (this example uses a variation of double checked locking).
Singleton is, of course, an "anti-pattern" (assuming a definition of a static with variable state).
If you want a fixed set of immutable value objects, then enums are the way to go. For a large, possibly open-ended set of values, you can use a Repository of some form - usually based on a
Map
implementation. Of course, when you are dealing with statics be careful with threading (either synchronise sufficiently widely or use aConcurrentMap
either checking that another thread hasn't beaten you or use some form of futures).Use getters and setters to set the variable and make the default constructor private. Then use: