Monday, March 18, 2013

Singleton Pattern

Singleton is a Creational Design Pattern. Often we may need to group a related members into a single class but only one instance of a class is enough for example Helper classes. We can solve this problem with many methods. A simple method would be using a static class with static methods.

 

// Singleton class
public static class Singleton {

    private static Data data;
    public static void commonMethod1() {
    }
    public static void commonMethod2() {
    }
}

 

As we marked the Singleton class as static, an instance to the Singleton class cannot be created. To access the singleton methods, we can directly invoke them using the class name as the methods are also static.

Singleton.commonMethod1();

 

Disadvantage of this implementation is we don’t have the control over the instantiation and destruction of this class as everything is defined as static.

 

To overcome this, we can implement the singleton pattern as below.

// Singleton class
public class Singleton {
    #region Singleton Implementation
    private static Singleton instance;

    static Singleton() {
        instance = new Singleton();
    }

    public static Singleton Instance {
        get {
            return instance;
        }
    }
    private Singleton() {
    }

    #endregion

    private Data data;
    public void commonMethod1() {
    }
    public void commonMethod2() {
    }
}

 

As we have declared the constructor as private, an instance to the singleton class cannot be created from outside of the class. A static instance variable is declared inside the class, the static constructor creates the default instance, and the Instance static property exposes the static singleton instance to others. Static constructor will be invoked when an instance of a method is created are static member is accessed. In this case the first call to the Instance static property will call the static constructor and will create the instance. Static constructors will not be called more than one time. So only one instance will be created in the static constructor and will be exposed through the Instance static property.

 

Above Singleton class can be accessed like

Singleton.Instance.commonMethod1();

 

Disadvantage of this method is the construction happens in the static constructor. If this class has another static method, invocation of that method will trigger the instantiation unnecessarily. To avoid that we can change this implementation as below.

 

// Singleton class
public class Singleton {
    #region Singleton Implementation
    private static Singleton instance;

    public static Singleton Instance {
        get {
           if (instance == null)
                instance = new Singleton();
            return instance;
        }
    }
    private Singleton() {
    }
    #endregion

    private Data data;
    public void commonMethod1() {
    }
    public void commonMethod2() {
    }
}

 

Instantiation is moved from static constructor to the Instance static property. So when the user tries to access the Instance first time, an instance will be created. Next time, as the instance variable is already assigned with an instance, it won’t instantiate again. So only one instance will be created here usually.

But when we use this code in multithreaded environment and if two or more threads tries to access the Instance, there is a possibility of creating more than one instance of this Singleton class (Which will be overwritten by the next thread executing the assignment). To avoid that we can use the locking mechanism of C#.

 

// Singleton class
public class Singleton {
    #region Singleton Implementation
    private static Singleton instance;

    public static Singleton Instance {
        get {
            lock (typeof(Singleton)) {
                if (instance == null)
                    instance = new Singleton();
            }
            return instance;
        }
    }
    private Singleton() {
    }
    #endregion

    private Data data;
    public void commonMethod1() {
    }
    public void commonMethod2() {
    }
}

 

Locking usually degrades the performance of the application. But to avoid creating multiple instance it becomes unavoidable to use locking.

No comments:

Post a Comment