ArticleS. UncleBob.
SingletonVsJustCreateOne [add child]

Singleton vs. Just Create One

The case against Singleton

The Singleton pattern is elegant and natural. It's easy to see why it's become so popular. In this article I'd like to convince you to avoid making a habit of using it.

The cannonical form of the Singleton pattern is:


public class Singleton
{
private Singleton() {}
private static Singleton instance = null;
public static Siggleton intance()
{
if (instance == null)
instance = new Singleton();
return instance;
}
}

This is so easy to understand, and so compelling in it's simplicity and convenience, that it has become one of the most popular of all the GOF design patterns. It seems to provide a way to mandate that no more than one instance of the Singleton object ever be created. Indeed, I have seen projects whose architectures are based on dozens of Singleton classes that form the entry points into the system.

But is Singleton the best way to achieve this? The Single Responsibility Principle (SRP) states that a class should have one and only one responsibility. A Singleton, by it's very nature, has at least two responsibilities. The first it it's primary function. The second it to ensure that only one instance be created. A strict interpretation of the SRP would suggest that one of those responsibilities should be moved out of the class.

Principles, however, are not laws. The benefits of Singleton may outweigh the subtle influence of an abstract principle. So we need more than just the SRP to make a case for avoiding Singleton. Pursuant to that end, consider this common variation of the Singleton (Which I will call SIS for Statically Initialized Singleton):


public class Singleton
{
private Singleton() {}
private static Singleton instance = new Singleton();
public static Singleton instance() {return instance;}
}

Clearly SIS is superior to the cannonical case in just about every way. It is faster, smaller, and simpler. The only benefit that cannonical Singleton has over thSIS is lazy evaluation. That is, the cannonical case does not make you pay for the creation of the Singleton unless you actually use it. (Of course this benefit is dubious at best. Why would you include a class that you did not intend to use?)

I can improve upon the SIS pattern, however. What you see below is something I call SINS for Statically Initialized Non-Singleton.:


public class Singulizer
{
public static NonSingleton nonSingleton = new NonSingleton();
}

public class NonSingleton
{
public NonSingleton() {}
}

Here I have conformed to the SRP by separating the enforcement of the singularity rule, from the class itself. It is the role of the Singulizer class to enforce singularity. You may protest that since the constructor of NonSingleton[?] is now public, there is no enforcement of singularity. True enough, the "enforcement" is by convention only. There would be a solution for this in C++. We could make the constructor of NonSingleton[?] private, and allow Singulizer to be a friend. Java, alas, does not give us this option.

We can enforce the convention by doing something draconian like this:

public class Singulizer
{
private Singulizer() {}
public static NonSingleton nonSingleton = new NonSingleton(new Singulizer());
}

public class NonSingleton
{
public NonSingleton(Singulizer s) {assert(s != null);}
}

But... eeeewwwwww!!

Besides, what are we afraid of? Can't we just tell our development team not invoke the constructor of NonSingleton[?]? Don't we trust our own teammates?

I understand that there are some cases (e.g. the creation of widely distributed libraries) where trusting teammates is not a viable solution to preventing unwanted multiple instantiations. On the other hand, most of us don't have that constraint. Most of us can simply attend a stand-up meeting, or a daily scrum, or some other group gathering and say: "Hay, don't anybody create instances of NonSingleton[?].

However, if we are going to trust our teammates to obey conventions (isn't that the definition of a team?) then why bother encapsulating the convention into a class. Why not simply create the single instances in main() and pass them into the rest of the system:


public static void main(String[] args)
{
MySystem s = new MySystem(new NonSingleton());
s.doWhatever();
}

I call this the Just Create One pattern, or JCO for short.

Now, if I haven't convinced you yet that Singleton should be avoided in most cases, consider the fact that Singleton makes it very hard to write unit tests. When we write unit tests, we want them to be independent from each other. We don't want Test2 to depend on the results of Test1. Indeed, we want to be able to run any test at any time in any order we wish. (Testing independence is a long held principle that I don't feel the need to defend here. But perhaps I'll defend it in another blog.) Singleton makes it very difficult to follow that rule without hauling down the entire execution context (e.g. JVM) for each test. What I want to do is create a new instance of the Singleton for each test case that I execute. However, this is precisely what Singleton prevents me from doing.

In my stilted view of the universe anything that impedes testing is something to be avoided. There are those who don't agree with this view, but I'll pit my defect rates against theirs any time. Testing considerations are very high on my list of important things, and I will gladly adjust my software designs to increase testability.

OK, having said all this, do I really avoid using Singleton? Yes, but I don't make a religion out of it. As I said above, there are cases where Singleton might make a certain kind of sense - especially if you don't trust the developers who will be using your classes. But in most instances, I think the very concept of singleness is flawed.



Append comments below:







public class Singleton
{
private Singleton() {}
private static Singleton instance = null;
public static Singleton instance()
{
if (instance == null)
setSingleton(new Singleton());
return instance;
}
public static void setSingleton(Singleton singleton){
instance = singleton;
}
}
public class TestCase{
public void setup(){
Singelton.setSingleton(new TestSingleton());
}
}

public class MainClass{
// No need to do anything. Just use lazy initialization
}



















Actually, the word should be "until" and not "unless". There's a big difference. Lazy initialization allows you to initialize a system without having to figure out (and and maintain) the correct initialization sequence.







public final class Singleton() {
private static Singleton instance;

private Singleton() { }

public static Singleton getInstance() {

if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}

return instance;
}

}

This way should work just fine. Reference: Head First Design Patterns (ISBN 0596007124)

 Mon, 10 Oct 2005 16:42:20, SeeR[?], IServiceProvider
I'm programming in C#, and whenever I want a singleton I use IServiceProvider as it's described in here: http://weblogs.asp.net/cazzu/archive/2004/05/10/129140.aspx
Not only it simplifies testing, but also it allows to choose implementation at higher level.
Instead of singleton I just think about service. In all cases I want singleton, it worked very well.
 Sun, 19 Feb 2006 12:02:56, Chip, Trusting your teammates?
My only concern is over the issue of trusting teammates. Developers come and go. Intentions are forgotten over time. In many cases software is developed by one team and handed over to another team to maintain.
 Mon, 20 Feb 2006 09:21:17, Ravi Venkataraman, Singletons
Singletons have their use. I use Singleton to store static (lookup) data so that any class that needs it can have access to it. This class (called ConfigData[?]) is initialized at start-up time only, lookup and configuration data can be "reloaded" at will. Nothing else can change its state. Hence, many of the problems mentioned in this article and the comments simply do not occur.

The other time I may use a Singleton is something like an Application class. generally, I use it to initialize application specific data at start-up. Once again, we have at most one such class in the application, and it is initialized at start-up and state change can only occur by re-loading it. Hence, we manage to avoid all these problems.

Unit testing is not a problem at all. If a class depends on the data loaded by the Singleton class, just use the Singleton.getSingleton() static method. If it is already loaded, then it will simply get the pre-loaded data and not load it again.