Singleton Pattern

In this blog post, I will try to create an example demonstrating the usage of singleton pattern.
When:
  • for situations where you only need one and only one object to exist
  • class needs to be accessible to clients
  • class should not require any parameters for its object creation
  • if creating an object is expensive, singleton can be useful
How:
In this example, we will try to create a LoadBalancer. LoadBalancer monitors the memory, processor resources etc and then decides which server to assign a particular task to. We won't create all those details as they are not necessary for this demonstration. Instead, we will use the C# Random class to make that decision. Why we need singleton pattern in this case? Because we don't want multiple instances of LoadBalancer. There should only be one LoadBalancer who makes the decision about multiple servers. Let's take a look at the consumer code first:

static void Main(string[] args)
        {
            SingletonPatternExample();

            Console.ReadLine();
        }

        private static void SingletonPatternExample()
        {
            for (int i = 0; i < 20; i++)
            {
                LoadBalancer lb = LoadBalancer.GetLoadBalancer();
                Console.WriteLine("Task " + i + " is assigned to " + lb.Server);
                System.Threading.Thread.Sleep(1000);
            }
        }
In this code, I just have a simple for loop to imitate tasks coming in. For every task, we get the LoadBalancer object and assign the Server to it randomly. For this example, you can argue that we could have achieved the same result by declaring the LoadBalancer object outside the for loop. That is true, but that is not the point of this demo. The point here is that singleton pattern is proactively stopping any new instances being created. Let's take a look at the LoadBalancer class now.

sealed class LoadBalancer
    {
        // Static members are lazily initialized. 
        // .NET guarantees thread safety for static initialization 
        private static readonly LoadBalancer instance = new LoadBalancer();

        private ArrayList servers = new ArrayList();
        private Random random = new Random();

        // Note: constructor is private.
        private LoadBalancer()
        {
            // List of available servers 
            servers.Add("Server 1");
            servers.Add("Server 2");
            servers.Add("Server 3");
            servers.Add("Server 4");
            servers.Add("Server 5");
        }

        public static LoadBalancer GetLoadBalancer()
        {
            return instance;
        }

        // Simple, but effective load balancer 
        public string Server
        {
            get
            {
                int r = random.Next(servers.Count);
                return servers[r].ToString();
            }
        }
    } 
The class is sealed so that it can not be inherited. Then we define a LoadBalancer instance as private and as static. If you don't define it a static then its not thread-safe. The class also has an ArrayList of servers and a Random object. The class also has a private constructor which just adds the servers to the ArrayList. Private constructor makes sure that class can not be initialized outside the scope. The GetLoadBalancer() method returns the one and only instance. There is no other way to get hold of this instance. And lastly, the simple Server property does the main work of finding out a Server and then notifying it to the caller.
Here are the results:



No comments: