Singleton Pattern

Posted: February 27, 2014 in Creational Patterns, Design Patterns
Tags: , ,

In the above video, Jamie King of computersciencevideos.org explained singleton pattern and its comparison with static class in an elegant manner.

The singleton pattern is a design pattern that restricts the instantiation of a class to one object.

This is useful when exactly one object is needed to coordinate actions across the system. For example, we only need only once instance of logging file. One instance can be shared across multitude of other clients.

Definition

Ensure a class has only one instance and provide a global point of access to it.

Participants

The classes and/or objects participating in this pattern are:

  • Singleton   (LoadBalancer/Logger)
    • Defines an Instance operation that lets clients access its unique instance. Instance is a class operation.
    • Responsible for creating and maintaining its own unique instance.

Sample Code:

namespace SingletonPattern
{
    class Logger
    {
        private static Logger _logger;

        private Logger(){}

        public static Logger GetInstance()
        {
            if (_logger == null)
            {
                _logger = new Logger();
            }

                return _logger;

        }

        public void WriteToFile()
        {
            //Add code to write to a file
            Console.WriteLine("Wrote to a file");
        }

    }
}

namespace SingletonPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Logger log = Logger.GetInstance();
            log.WriteToFile();
            Console.ReadKey();
        }
    }
}

Another Example


// Singleton pattern -- .NET optimized

using System;
using System.Collections.Generic;

namespace DoFactory.GangOfFour.Singleton.NETOptimized
{
    /// <summary>
    /// MainApp startup class for .NET optimized
    /// Singleton Design Pattern.
    /// </summary>
    class MainApp
    {
        /// <summary>
        /// Entry point into console application.
        /// </summary>
        static void Main()
        {
            LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
            LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
            LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
            LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

            // Confirm these are the same instance
            if (b1 == b2 && b2 == b3 && b3 == b4)
            {
                Console.WriteLine("Same instance\n");
            }

            // Next, load balance 15 requests for a server
            LoadBalancer balancer = LoadBalancer.GetLoadBalancer();
            for (int i = 0; i < 15; i++)
            {
                string serverName = balancer.NextServer.Name;
                Console.WriteLine("Dispatch request to: " + serverName);
            }

            // Wait for user
            Console.ReadKey();
        }
    }

    /// <summary>
    /// The 'Singleton' class
    /// </summary>
    sealed class LoadBalancer
    {
        // Static members are 'eagerly initialized', that is,
        // immediately when class is loaded for the first time.
        // .NET guarantees thread safety for static initialization
        private static readonly LoadBalancer _instance =
          new LoadBalancer();

        // Type-safe generic list of servers
        private List<Server> _servers;
        private Random _random = new Random();

        // Note: constructor is 'private'
        private LoadBalancer()
        {
            // Load list of available servers
            _servers = new List<Server>
        {
         new Server{ Name = "ServerI", IP = "120.14.220.18" },
         new Server{ Name = "ServerII", IP = "120.14.220.19" },
         new Server{ Name = "ServerIII", IP = "120.14.220.20" },
         new Server{ Name = "ServerIV", IP = "120.14.220.21" },
         new Server{ Name = "ServerV", IP = "120.14.220.22" },
        };
        }

        public static LoadBalancer GetLoadBalancer()
        {
            return _instance;
        }

        // Simple, but effective load balancer
        public Server NextServer
        {
            get
            {
                int r = _random.Next(_servers.Count);
                return _servers[r];
            }
        }
    }

    /// <summary>
    /// Represents a server machine
    /// </summary>
    class Server
    {
        // Gets or sets server name
        public string Name { get; set; }

        // Gets or sets server IP address
        public string IP { get; set; }
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s