Showing posts with label Design Patterns. Show all posts
Showing posts with label Design Patterns. Show all posts

Thursday 30 September 2010

Design Patterns ~ Singleton Pattern using C#

It is considered as the simplest of patterns. Main objective of singleton pattern is to restrict the instantiation of a class to a singe object. It can be implemented like this.

public class Singleton {
private static Singleton _instance;

private Singleton() {

}

public static Singleton Instance {
get{
if(_instance == null){
_instance = new Singleton();
}
return _instance;
}
}
}

The above mentioned implementation has advantages and disadvantages. The main advantages are :



  1. Since the instance is created inside the ‘Instance’ property, the class can handle additional functionality like instantiating a subclass.

  2. Lazy Instantiation’ approach. That is, instantiation of the class is not performed, till an object asks for an instance. This will avoid instantiating unnecessary  singletons when the application starts.

And the main disadvantage of this approach is, that this is not ideal for multithreaded environments. If separate threads of execution enter the Instance property method at the same time, more that one instance of the Singleton object may be created. Each thread could execute the following statement and decide that a new instance has to be created.

if(_instance == null)

 


The most common and suitable solution to overcome this is to use the ‘Double-Check Locking’. This will keep separate threads from creating new instances of the singleton at the same time.

public class Singleton {
private static volatile Singleton _instance;
private static object syncRoot = new object();

private Singleton() {

}

public static Singleton Instance {
get{
if(_instance == null){
lock (syncRoot) {
if (_instance == null) {
_instance = new Singleton();
}
}
}
return _instance;
}
}
}
This method make sure that only one instance is created and only when the instance is required. Making the variable ‘volatile’ make sure that assignment to the instance variable completes before the instance variable can be accessed. And in order to avoid deadlocks it uses a separate object to lock on, rather than using the type itself.