Singleton Design Pattern

From OasisSoftTech.com - Knowledge Base/Java/Springframework/Microservices/Cloud-AWS/AI
Revision as of 15:13, 30 July 2018 by Rasimsen (talk | contribs) (Questions & Answers)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Singleton Design Pattern | Implementation

The singleton pattern is one of the simplest design patterns. Sometimes we need to have only one instance of our class for example a single DB connection shared by multiple objects as creating a separate DB connection for every object may be costly. Similarly, there can be a single configuration manager or error manager in an application that handles all problems instead of creating multiple managers.

Definition

The singleton pattern is a design pattern that restricts the instantiation of a class to one object. Let’s see various design options for implementing such a class. If you have a good handle on static class variables and access modifiers this should not be a difficult task.

Method 1: Classic Implementation

// Classical Java implementation of singleton 
// design pattern
class Singleton
{
    private static Singleton obj;
 
    // private constructor to force use of
    // getInstance() to create Singleton object
    private Singleton() {}
 
    public static Singleton getInstance()
    {
        if (obj==null)
            obj = new Singleton();
        return obj;
    }
}

Here we have declared getInstance() static so that we can call it without instantiating the class. The first time getInstance() is called it creates a new singleton object and after that it just returns the same object. Note that Singleton obj is not created until we need it and call getInstance() method. This is called lazy instantiation.

How to Singleton in Tread

The main problem with above method is that it is not thread safe. Consider the following execution sequence.

singleton-1.png

This execution sequence creates two objects for singleton. Therefore this classic implementation is not thread safe.

Method 2: make getInstance() synchronized

// Thread Synchronized Java implementation of 
// singleton design pattern
class Singleton
{
    private static Singleton obj;
 
    private Singleton() {}
 
    // Only one thread can execute this at a time
    public static synchronized Singleton getInstance()
    {
        if (obj==null)
            obj = new Singleton();
        return obj;
    }
}


Here using synchronized makes sure that only one thread at a time can execute getInstance(). The main disadvantage of this is method is that using synchronized every time while creating the singleton object is expensive and may decrease the performance of your program. However if performance of getInstance() is not critical for your application this method provides a clean and simple solution.

Method 3: Eager Instantiation

// Static initializer based Java implementation of
// singleton design pattern
class Singleton
{
    private static Singleton obj = new Singleton();
 
    private Singleton() {}
 
    public static Singleton getInstance()
    {
        return obj;
    }
}

Here we have created instance of singleton in static initializer. JVM executes static initializer when the class is loaded and hence this is guaranteed to be thread safe. Use this method only when your singleton class is light and is used throughout the execution of your program.

Method 4 (Best): Use “Double Checked Locking”

If you notice carefully once an object is created synchronization is no longer useful because now obj will not be null and any sequence of operations will lead to consistent results. So we will only acquire lock on the getInstance() once, when the obj is null. This way we only synchronize the first way through, just what we want.

// Double Checked Locking based Java implementation of
// singleton design pattern
class Singleton
{
    private volatile static Singleton obj;
 
    private Singleton() {}
 
    public static Singleton getInstance()
    {
        if (obj == null)
        {
            // To make thread safe
            synchronized (Singleton.class)
            {
                // check again as multiple threads
                // can reach above step
                if (obj==null)
                    obj = new Singleton();
            }
        }
        return obj;
    }
}

We have declared the obj volatile which ensures that multiple threads offer the obj variable correctly when it is being initialized to Singleton instance. This method drastically reduces the overhead of calling the synchronized method every time.


Questions & Answers

If somebody will call instance.clone() method, will it create copy of our Singleton class?

So, if we are not implementing Cloneable interface in our Singleton class, then we do not require to prevent cloning. Java will do it for us.


How do you create a Singleton in Java?

Objects are created using constructors. In order to be create the restriction you need to remove this ability. This can be done in Java using a private constructor. This means that only static methods in the class itself can create the object. An accessor method is then provided which makes the single instance of the object available.

How do you cope with thread safety when creating a Singleton?

Make the getInstance() block synchronized. This ensures that only one thread can access the method at once. This however will make all calls to getInstance() syncronized which could result in performance degredation

What is the difference between lazy and eager instantiation? Why does it matter?

Due to the lazy instantiation, that is, the fact the object is not created until it is first needed, the code sample above is not threadsafe. If multiple threads try to simultaneously access the Singleton it can result in 2 objects getting created, thus defeating the purpose of the pattern. There are two ways around this:

  • Make the getInstance() block synchronized. This ensures that only one thread can access the method at once. This however will make all calls to getInstance() syncronized which could result in performance degredation
  • Use Eager Initialisation. By initialising on the field the object is guaranteed to be ready before access, eliminating threading and performance issues.

But when do you choose between lazy and eager initialisation? Lazy initialisation defers creation of an object until you absolutely need it. If it’s an “expensive” object like a database connection for example, it could in theory be good to use lazy initialisation if there’s a chance the connection won’t be needed. However, the benefit of lazy is simply that you will speed up your start up time. If startup times are not a concern for you (and generally they aren’t), go with eager initialisation as it solves a lot of problems with threading. The simple fact is Threading is hard and if you can avoid things like syncronized then the trade off is worth it.

Are singletons a good pattern to use?

How do singletons affect testing?

Singletons are not a good coding practice as they cause high coupling and violate dependency injection principles. This makes code really hard to test. Any object making use of a singleton needs to use a static method to get access to it. This means it is not being “injected” in and so cannot be stubbed out for use in testing. This can cause real problems as Singletons are often used to manage resources.

In the above example I want to unit test the doSomethingThatICanUnitTest() method to ensure it returns 17. However, when I try to create this class in my test it will force the creation of a SingletonExample object and any expense that it has. If it’s a database connection for example, that means my unit test will try and connect to the database as part of my unit test which is terrible. Dependencies should be injected in so that I can mock them out and test the behaviour I actually care about. Singletons break this. As a result they are often avoided in reality, although they are the most well known pattern and so are often used as an interview question.