Design Patterns

           Singleton Design Pattern


Some types have not any reason to instantiate more then once in a project. For example creating a database connection every time take some costs or creation of logger in a project also consume memory of object creation each time. To avoid this we need to make a type as singleton by doing this we can instantiate it only one time and use it anywhere throughout the application or module.
                     Sometimes we have a task to read some data from file, so we can create a single instance of object that read data from file and share it through the project to consumers.
                     Let's start with creating a singleton class. To achieve this we have created an interface that contains one method of SingletonContainer class.

 public interface ISingletonContainer
    {
         int GetPopulation(string name);
    }

we will create a class that read the population data from file in a constructor and returns population by using GetPopulation method.

class SingletonContainer:ISingletonContainer {
        private Dictionary<String, int> _capital = new Dictionary<string, int>();
        private SingletonContainer()
        {
            Console.WriteLine("Initializing Singleton object");

            var elements = File.ReadAllLines("Population.txt");
            for(int i=0;i<elements.Length;i+=2)
            {
                _capital.Add(elements[i], int.Parse(elements[i + 1]));
            }
        }

        public int GetPopulation(string name) {
            return _capital[name];
        }

        public static SingletonContainer instance = new SingletonContainer();
        public static SingletonContainer Instance => instance;
  }

Steps to create a Singleton instance:
1) Make the constructor private so that no one consumer can access it.
2) Create a new instance of Singleton class.
2) Define a static reference variable of the class and assign instance to it.
In the above example we have created instance of SingletonContainer class and expose it by using Instance property.
 So finally we have created a Singleton object but to make it more specific we need to make it thread safe.
Thread Safety: We will use the Lazy type to instantiate SingletonContainer class one when it needed first time.

class SingletonContainer:ISingletonContainer {
        private Dictionary<String, int> _capital = new Dictionary<string, int>();
        private SingletonContainer()
        {
            Console.WriteLine("Initializing Singleton object");

            var elements = File.ReadAllLines(@"F:\My\DesignPattern\Signleton\code\File\Population.txt");
            for(int i=0;i<elements.Length;i+=2)
            {
                _capital.Add(elements[i], int.Parse(elements[i + 1]));
            }
        }

        public int GetPopulation(string name) {
            return _capital[name];
        }

        public static Lazy<SingletonContainer> instance = new Lazy<SingletonContainer>(()=>new SingletonContainer());
        public static SingletonContainer Instance => instance.Value;

    }
we have to just call Instance property as following and our object is ready. At this point we can call our instance property as many time we want but our object is going to instantiate only once and shared for every other call. It will load in a lazy way it means our instance is going to be created only the first time it needed.

class Program
    {
        static void Main(string[] args)
        {
            var db2=SingletonContainer.Instance;
            Console.WriteLine(db2.GetPopulation("NewDelhi"));
            var db3 = SingletonContainer.Instance;
            Console.WriteLine(db2.GetPopulation("Lucknow"));
            Console.ReadLine();
            
        }
    }

We can also check if our object is created by IsValueCreated property of instance.







Comments

Popular posts from this blog

Threading and Task Processing Library in C#