Singleton an anti-pattern?

The singleton pattern is a widely used design pattern, which allows us to have only one instance of a class. Although using a singleton can have its benefits, there also a number of drawbacks which should convince you to use singletons wisely. Due to the drawbacks of the singleton pattern, this pattern is also referred to as a anti-pattern. An anti-pattern is a design pattern, which is in some ways in-effective or has drawbacks.

The happy side of using singletons

Look at the usefulness of the singleton. When could you use this pattern? A logging class most of the time use the singleton pattern. You can access the logging class from everywhere in your program, without having to allocate, initialize or cleanup memory. You can simple start logging by using commands like this:
Log.Trace("Putting a trace logging");


Having only one instance of an object has also many drawbacks. We will look at the two main drawbacks: unit-testing and multithreaded environments.


It is very difficult to unit-test classes which uses this pattern. When you execute your unit tests in one single executable, the object will be created the first time you access it via the unit test and will be cleaned up after closing the latest unit test. Since the object can be used by many other classes, you don’t now the state of your object. You want to behave unit-tests in depended of each other. But since an unit-test now leaves an instance in a different state it created it, you create a dependency between unit-tests. Running unit-test X before Y, could have a different result than running unit-test Y before X.
When executing your unit-tests and checking for memory leaks, the singleton classes will leak memory. This is due the fact the singleton instance will not be deallocated. This makes it harder to trace down the real memory leaks in your program.


Another problem is when you use singletons in multi-threaded environments. Think of the following many used implementation in C#:
 1. public class MySingleton
 2. {
 3.     public static MySingleton GetInstance
 4.     {
 5.        get
 6.        {
 7.             if (instance == null)
 8.             {
 9.                  m_instance = new MySingleton();
10.              }
11.              return m_instance;
12.         }
13.   }
15.   private MySingleton () {}
17.   private static MySingleton m_instance;
18. }

The way the instance of MySingleton is created, is referred as lazy initialisation. This means, the instance is created at exact the moment the instance is needed the first time. What if two threads try to access the GetInstance property at the beginning of executing of the program. In this case, m_instance is null. When both threads check on line 7 if instance is null and if they conclude it is indeed null, they both create a new instance of the class.

A way to prevent this is by adding a semaphore and lock it when you get before the check if instance is null. This would be something like this:

 1. public class MySingleton
 2. {
 3.   public static MySingleton GetInstance
 4.   {
 5.        get
 6.        {
 7.             lock(myLock)
 8.             {
 9.                  if (instance == null)
10.                   {
11.                        m_instance = new MySingleton();
12.                   }
13.              }
14.              return m_instance;
15.         }
16.   }
18.   private MySingleton () {}
20.   private static MySingleton m_instance; 
21.   private static object myLock = new Object(); 
22. }
The myLock instance is initialised again in a lazy way. When we would initialize m_instance in this way, it is still not garuanteed that m_instance is initialised only one time. The myLock instance can be created multiple times, but this is cleaner than the problem of initialising the m_instance property multiple times.


You should use the singleton pattern wisely. In some ways it is indeed an anti-pattern, but for example when using a logging class it can be quite handy. Also be very careful when using singletons within unit-tests!

Posted in Design patterns by Bruno at January 8th, 2014.
Tags: , ,

Leave a Reply