Tuesday, February 18, 2014

Common Design Patterns in C# 4.0- Singleton Pattern


Hello again ,
Last time we discussed about different Factory Patter .
This time we will learn about the Singleton Pattern.
THis article is at CodePlex 
Pattern Name:
Singleton Pattern
Short Description:
Class with only one single possible instance
Usage:
Often used for objects that need to provide global access with the constraint of only one single instance in the application
Complexity:
1 / 5
UML Class Diagram:
image_thumb2_thumb[2]
Explanation:
  • There are multiple ways of implementing the Singleton Pattern in C#. I am going to explain the most efficient approaches that also provide thread safety.
  • Note that in the first example the default constructor is defined as private so that it is not possible to instantiate the object from the outside. The class is also marked as sealed which means that inheritance is not allowed for it.
  • The internally instantiated object is stored in a private variable that is marked as static. The public static property GetInstance is used to allow access to this object. It contains the business logic that assures that only a single instance can ever exist.
  • To achieve this behavior a lock strategy is used to assure that only a single thread is allowed to do the null check and create a new instance if it does not already exist.
  • A test function DisplayConfiguration() was added to be able to verify the class design.
    public sealed class ConfigurationManager
    {
        private static ConfigurationManager instance;
        private static object syncRoot = new Object();

        private ConfigurationManager()
        {
       
        }

        public static ConfigurationManager GetInstance
        {
            get
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new ConfigurationManager();
                    }
                }

                return instance;
            }
        }

        public void DisplayConfiguration()
        {
            Console.WriteLine("Single instance object");
        }
    }
  • Note that in the second example the default constructor is also defined as private so that it is not possible to instantiate the object from the outside. The class is also marked as sealed which means that inheritance is not allowed for it.
  • This time a private nested class is used to provide access to the instance that must only exist once in the application.
  • This nested class has a static default constructor and an internal static read-only instance of the object. Only the container class has access to the instance which will due to the software design (auto-instantiated and marked as read-only) only exist once.
  • A test function DisplayRules() was added to be able to verify the class design.
  • I recommend using this example as your default approach for your Singleton implementations since there is no locking in it which makes it more efficient in terms of performance.
    public sealed class BusinessRulesManager
    {
        private BusinessRulesManager()
        {

        }

        public static BusinessRulesManager GetInstance
        {
            get
            {
                return BusinessRulesManagerImpl.instance;
            }
        }

        public void DisplayRules()
        {
            Console.WriteLine("Single instance object");
        }

        private class BusinessRulesManagerImpl
        {
            static BusinessRulesManagerImpl()
            {

            }

            internal static readonly BusinessRulesManager instance = new BusinessRulesManager();
        }
    }
  • In the last step we add some code to test the software design and the Singleton implementation.
    private static void Singleton()
    {
        var configurationManager = ConfigurationManager.GetInstance;
        configurationManager.DisplayConfiguration();

        var businessRulesManager = BusinessRulesManager.GetInstance;
        businessRulesManager.DisplayRules();

        Console.ReadKey();
    }
  • When running the example you can see that everything is working as expected (it is however not as simple to test that there really is just one single instance, you just have to believe in the correct software design).
image_thumb_thumb[1]





Regards
Amey 
Start where you are. Use what you have.  Do what you can.

No comments:

Post a Comment