Design Patterns Series 7 - Singleton Pattern

In the previous post we explained chain of responsibility pattern, this post we will be about taking control of the number of objects you have floating around in your code.There are two pattern, Singleton Pattern and Flyweight Pattern.

Singleton Pattern:
It is all about making sure that you can instantiate only one object of a particular class, if you don't use a pattern like this one,the new operator just keeps on creating more and more objects of the same class. Using singleton pattern make sure you only have one object, no matter how many times someone's code tries to create more objects.

You use it when you want to either restrict resource use, or when you have a sensitive objects whose data shouldn't be accessed by multiple instances. Also you can use it when you want to restrict the number of objects created because you want to share the data in those objects and you don't want to create multiple objects, which might confuse access to that data.

Creating a singleton object can also be important when you are multi-threading and you don't want conflicts in how the data behind  that objects is accessed. Any time you really want to only one object of a certain class, check out the singleton pattern instead of the new operator, it will get the job done.

Now is the time to write some code to know how to create singleton pattern. Consider we have class named Database contains one method(EditRecord()) and one properties(Name).
public class Database
{
   private Int32 record;
   public String Name
   {
      get;
      set;
   }
   
   public Database(String name)
   {
      this.Name = name;
      record = 0;
   }
   public void EditRecord(String operation)
   {
      Console.WriteLine("Performing a {0} operation on record {1} in database {2}" , operation , this.record , this.Name);
   }
}
Now the issue is if you used new operator to create object of Database class, and you uses this class three times, you will have three different objects of the same class.
Database database_1 = new Database("Employee");
Database database_2 = new Database("Employee too");
Database database_3 = new Database("Employee again");
To avoid creating a new object by using new operator you can declare the constructor as private but that means no one on the earth will be able to create any object of Database class using new operator because its constructor will not be callable from outside.

But we can use a utility method inside Database class to create an object of it. First, make its constructor private, that will block the use of new operator from outside Database class but allow using it form inside, yes inside the utility method which should be public and static (becuase of private constructor) and we will call it CreateInstance() that will return an object of Database class but that only works when there is one of those in existance.

The code in this method first checks if that object exists, and if not , it will create it then returns.
public class Database
{
   private static Database singleObject;
   private Int32 record;
   public String Name
   {
      get;
      set;
   }
   private Database(String name)
   {
      Name = name;
      record = 0;
   }
   public void EditRecord(String operation)
   {
      Console.WriteLine("Performing a {0} operation on record {1} in database {2}" , operation , record , Name);
   }
   public static Database CreateInstance(String name)
   {
      if(singleObject == null)
      {
         singleObject = new Database(name);
      }
      return singleObject;
   }
}
lets test what we wrote with the following code fragment
Database myDatabase = Database.CreateInstance("Employees");
Console.WriteLine("This is the {0} database" , myDatabase.Name);

myDatabase = Database.CreateInstance("Employee too");
Console.WriteLine("This is the {0} database" , myDatabase.Name);
that will print out
This is the Employees database
This is the Employees database
note although we re-declared myDatabase object with Employees too as argument, the out put still Employees, that means we succeeded to keep our code create just one object of Database class.

But what about multi-threading application, will this code create one object when two different thread calling CreateInstance method at the same time and no Database object exists yet?. No it will create two objects, that mean we broke singleton pattern concept. One easy way to fix this is by locking the code that create the instance to make sure it is accessed by just one thread. To do that we will need to declare another object to handle locking process.
public class Database
{
   private static Database singleObject;
   private Object _sync = new Object();
   private Database()
   {
   }
   public String Name
   {
      get;
      set;
   }
   public static Database CreateInstance(String name)
   {
      lock(_sync)
      {
         if(singleObject == null)
         {
            singleObject = new Database(name);
         }
      }
      return singleObject;
   }
}
As you see we locked the new object(_sync) that means it will be handled by just one thread at a time and if another thread want to access it, the second thread will wait until the first one finish its execution. lets test the multi-thread version of singleton pattern
public class Program  
{
    static void Main(string[] args)
    {
        Thread th1 = new Thread(th => TestThreading("Thread 1"));
        th1.Start();

        Thread th2 = new Thread(th => TestThreading("Thread 2"));
        th2.Start();
    }
    static void TestThreading(String name)
    {
        Database myDatabase = Database.CreateInstance(name);
        Console.WriteLine("This is the {0} database", myDatabase.Name);
    }
}
After running this example the out put will be
This is the Thread 1 database
This is the Thread 1 database
OR
This is the Thread 2 database
This is the Thread 2 database
According which thread run first. That mean regardless of number of threads that call CreateInstance method, just one and only one instance of Database class will be created.

you can download the full source code here

Comments

Popular posts from this blog

Android : How to change progress bar color at runtime programmatically?

ASP.Net MVC : Conditional Validation using ValidationAttribute

How to fire RowCommand event of nested GridView?