Well, maybe, maybe not, but Singletons can be fun. They keep several people referencing the same object. Many people have difficulty getting all the bits right, which can be a pain when a team out of your control starts instantiating your Singleton. Lets look at an archtypal singleton, what makes a guaranteed Singleton, and see what evening debauchery it can get into:
public final class Singleton {
private static Singleton instance;
private int data = 0;
private Singleton(){
data = 5;
}
public final int getData() { return data;}
public final static Singleton getInstance() {
if (instance == null) { // if it is not null dont do all this synchronization stuff:
synchronized(Singleton.class) {
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
}
I've drawn attention to the key points here with the bolded text. Let's go through these points one at a time and see what makes a Singleton and what makes a good one.
public final class Singleton {
Notice that we make the class final. If we didn't do this, anyone could extend our class, even trivially, and make multiple instantiations of it. The ways our Singleton bachelors could created are various. For example:
public class mySingleton extends Singleton {
public mySingleton() {}
public mySingleton getInstance() {return new mySingleton();}
/* or even a static method like: public static mySingleton getInstance() {return new mySingleton();} */
}
In this way, the constructor could be made public, allowing multiple creations, or the getInstance method could be overridden. Since all of these objects could be cast as Singletons, any presumptions about there being one and only one Singleton would be violated.
That was incredibly lame, I admit.
private Singleton(){
Remember to privatize the default null parameter constructor. By default, if you leave it out, a public constructor is presumed for the class. If we leave out all constructors, we dont get an unconstructable class, but rather one which has a default constructor that is public. That being said, remember to both include a default constructor and make the default constructor (and any other constructors of course) private, even if you don't use it.
You may not be coding a class for a multithreaded use, but who knows what the future holds? Consider the following code:
if (instance == null) {
instance = new Singleton();
}
return instance;
As such, however unlikely, it is possible that two threads of control could be invoking the getInstance method at the same time and the first is suspended after the null check but before the line which sets the instance. Then the second thread starts up and the method is invoked. Since the instance was net yet set by the other thread, it is still null, so the second thread sets it to a new instance. Now the first thing that happens when the first thread of control resumes is that is sets the instance to a new Singleton. The method returns and now we have two threads with two different Singletons. Another inconsistency. This is unlikely to happen, but it was also unlikely anyone would be COBOL code that used 2-digit year representations into the next century and that brought about global catastrophe that we still have not recovered from [ed. note - published pre-emptively in 1999]. So lets use the handy synchronization of Java:
synchronized(Singleton.class) {
if(instance==null){
instance = new Singleton();
}
}
Now the check-and-set will act as an atomic operation, and it is no longer possible that two threads can end up with two different singletons (well actually, it probably wasn't going to happen anyways). Now synchronization involves the creation of a queue based monitor which is beyond what we are talking about here, but basically, every time this method is invoked we are creating extra work to do. What if I said you could replace all this work with one low cost boolean compare? How much would you pay then? 50 dollars? If so then mail me and let's do a deal. If not, here's the solution:
if (instance == null) { // if it is not null don't do all this synchronization stuff:
synchronized(Singleton.class) {
The logic being that if its not null, we just skip the synchronization bit and return it. Keep in mind another thread could have set it before we enter the synchronization block, so once we are in it, we must check again if it is null. The net effect is that we will check for null twice and synchronize only a couple of times (probably once) and thereafter we will skip the synchronization block and just check for null. No need to be lazy.
public class UsesSingleton {
public static void main(String[] args) {
java.util.Locale aLocale = new java.util.Locale("fr", "CA");
java.util.Locale.setDefault(aLocale);
Singleton onlyOne = Singleton.getInstance();
System.out.println("Singleton's data is: " + onlyOne.getData());
Singleton isItDifferent = Singleton.getInstance();
System.out.println("The statement: onlyOne = isItDifferent is: " + onlyOne.equals(isItDifferent));
}
}
So there you have it. And I'll throw in the steak knives for free:
private int numOfSteakKnives = 0;
public void throwInSomeSteakKnives(int numOfKnives) {
numOfSteakKnives += numOfKnives;
}