Tuesday, September 21, 2010

Singleton Design Pattern

Motivation:
Sometimes it is important to have only one instance of a class in the entire application. Usually singletons are used for centralized management of internal or external resources and they provide a global point of access to the instances of the Objects.

So, our intention is to
* Ensure that only one instance of a class is created.
* Provide a global point of access to the object.

Implementation:
The implementation has a static member in the "Singleton" class, a private constructor and a static public method that returns a reference to the static member.

The Singleton Pattern defines a getInstance operation which exposes the unique instance which is accessed by the clients. getInstance() is a class operation and is responsible for creating its own unique instance in case it is not created yet.

class Singleton
{
private static Singleton m_instance;
private Singleton()
{
...
}

public static synchronized Singleton getInstance()
{
if (m_instance == null)
m_instance = new Singleton();

return m_instance;
}
...
public void doSomething()
{
...
}
}

There are many common situations when singleton pattern is used:
- Logger Classes
- Configuration Classes
- Caching classes
- Accesing resources in shared mode
- Other design patterns implemented as Singletons: Factories and Abstract Factories, Builder, Prototype


Thread-safe implementation in multithreading access/usage of the single object:
1. Lazy instantiation
2. Early instantiation

1. Lazy instantiation using double locking mechanism:
The standard implementation shown in the code above is a thread safe implementation, but it's not the best thread-safe implementation beacuse sinchronization is very expensive when we are talking about the performance. We can see that the syncronized method getInstance does not need to be checked for syncronization after the object is initialized. If we see that the singleton object is already created we just have to return it without using any syncronized block. This optimization consist in checking in an unsincronized block if the object is null and if not, then check again and create it in an syncronized block. This is called double locking mechanism.

In this case case the singleton instance is created when the getInstance() method is called for the first time. This is called lazy instantiation and it ensures that the singleton instance is created only when it is needed.

class Singleton
{
private static Singleton m_instance;

private Singleton()
{
System.out.println("Singleton(): Initializing Instance");
}

public static Singleton getInstance()
{
if (m_instance == null)
{
synchronized(Singleton.class)
{
if (m_instance == null)
{
System.out.println("getInstance(): First time getInstance was invoked!");
m_instance = new Singleton();
}
}
}

return m_instance;
}

public void doSomething()
{
System.out.println("doSomething(): Singleton does something!");
}
}

2. Early instantiation using implementation with static field:
In the following implementattion the singleton object is instantiated when the class is loaded and not when it is first used, due to the fact that the m_instance member is declared static. This is why in this implementation we don't need to syncronize any portion of the code. The class is loaded once this guarantee the unicity of the object.

class Singleton
{
private static Singleton m_instance = new Singleton();

private Singleton()
{
System.out.println("Singleton(): Initializing Instance");
}

public static Singleton getInstance()
{
return m_instance;
}

public void doSomething()
{
System.out.println("doSomething(): Singleton does something!");
}
}

Issues:
Multiple singleton instances if classes loaded by different classloaders accessing a singleton:
If a class(same name, same package) is loaded by 2 diferent classloaders they represents 2 different clasess in memory.

Hope this is useful!

No comments:

Post a Comment