One Object to Rule Them All

If you ask a software engineer, especially someone just out of college, to name a design pattern, the most common answer, in my experience, is the Singleton. The internet is full of opinions on whether or not a singleton is good or bad and how it is different or essentially the same as a global or static variable. I don’t want to join that debate here. Instead, let’s discuss how to create a Singletong.
The typical way to do it goes something like (Java):
public class BasicSingleton {
private static BasicSingleton theOneObject;
private BasicSingleton() {}
public static BasicSingleton getSingleton() {
if (theOneObject == null) {
theOneObject = new BasicSingleton();
}
return theOneObject;
}
}
This works for basic non-threaded cases. To make it thread safe, some sort of locking is needed. The easiest way (in Java) to do this is to “synchronize” the getSingleton method, like:
public synchronized static BasicSingleton getSingleton() {
if (theOneObject == null) {
theOneObject = new BasicSingleton();
}
return theOneObject;
}
Now it is “safe” and ready to use. However, if this is needed for any performant application, the synchronized lock can cause noticeable performance slow downs. An optimization for this is to remove the synchronize indicator and use a mutex that is guarded by a null check, like:
private static Object mutex = new Object();
public static BasicSingleton getSingleton() {
if (theOneObject == null) {
synchronized (mutex) {
if (theOneObject == null) {
theOneObject = new BasicSingleton();
}
}
}
return theOneObject;
}
This is pretty performant as null checks are fairly cheap. However, there is another way to implement a singleton where the null check and mutex lock, essentially, only happen once.
In this solution, the method that returns the singleton object is replaced with a basic getter after the singleton is created.
public class LordOfTheObjects {
// this inline Summoner is only used the first time the singleton is requested
private static Summoner summoner = new Summoner() {
private LordOfTheObjects theOneObject; // this is the singleton object
private Object mutex = new Object();
@Override
public LordOfTheObjects summon() {
synchronized (mutex) {
if (theOneObject == null) {
theOneObject = new LordOfTheObjects();
}
}
// the summoner is replaced with an implementation that only returns the singleton object
LordOfTheObjects.summoner = new ObjectBearer(theOneObject);
return theOneObject;
}
};
private LordOfTheObjects() {}
public static LordOfTheObjects getTheLord() {
return summoner.summon();
}
}
public interface Summoner {
LordOfTheObjects summon();
}
public class ObjectBearer implements Summoner {
private LordOfTheObjects theOneObject;
public ObjectBearer(LordOfTheObjects theOneObject) {
this.theOneObject = theOneObject;
}
@Override
public LordOfTheObjects summon() {
return theOneObject;
}
}
There are different ways to accomplish this, especially if you can use function pointers. In this implementation, the magic is in the line:
LordOfTheObjects.summoner = new ObjectBearer(theOneObject);
This replaces the method that retrieves the singleton after it has been created. Now there is merely a method call instead of the null check. This is similar to the classic State Design Pattern.
How is this better? Honestly, I’m not sure that it is better. I’ve never used it in production code. It is arguably a more complicated implementation. It probably isn’t noticeably more performant than the double null check solution. However, I do think it is more elegant. Elegance has a certain “better” quality to it. It also helps think of the problem in a different way, and that is useful.