Singleton Pattern

This Pattern lets you ensure that a class has only one instance, which provides global access point to this instance. Where this pattern is best suited?When you have a database or a file and you

This Pattern lets you ensure that a class has only one instance, which provides global access point to this instance.

Where this pattern is best suited?
When you have a database or a file and you want only one person to be able to access it.

Please note singleton are very expansive and bad. As singleton gives us global access it becomes were tough for implementing the automated testing.
Plus classes will know about each other and they will become dependent on each other.
They violate the SOLID principles

Possible alternative for a singleton pattern would be dependency injection.

Lets say we have a class called Singleton which has a method called Printmessage to print messages to the screen and from main you are sending messages to it and everytime when sending you create an object of this Singleton class like below

Normal Code:

using System;

namespace design_patterns
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton msg1 = new Singleton();
            msg1.PrintMessage("Design patterns are simple");

            Singleton msg2 = new Singleton();
            msg2.PrintMessage("If time is spent on it");
            Console.WriteLine("Hello World!");
            Console.ReadLine();
        }
    }
}

using System;
namespace design_patterns
{
    class Singleton
    {
        //counter will track the number of times this call is instantiated
        //Every-time we create an instance of a class counter will also gets created
        //to avoid that we are using static
        private static int counter = 0;
        public Singleton()
        {
            counter++;
            Console.WriteLine("Singleton object creation number: {0}", counter);
        }
        public void PrintMessage(string message)
        {
            Console.WriteLine(message);
        }
    }
}

There are 3 big problems with the above code
1. Everytime we want to print message we create a new object and objects take space and memory
2. This class can be inherited and instantiated from derived class through which users can create objects so make the class as sealed.
3. By having public constructors users will still be able to create object of this class outside of the class make it private and take away that ability

LazyLoading:

using System;

namespace design_patterns
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton msg1 = Singleton.getInstance;
            msg1.PrintMessage("Design patterns are simple");

            Singleton msg2 = Singleton.getInstance;
            msg2.PrintMessage("If time is spent on it");
            Console.WriteLine("Hello World!");
            Console.ReadLine();
        }
    }
}

using System;

namespace design_patterns
{
    //If this class is not sealed it can be inherited
    //from other class (given that class is within this class
    //nested class)
    public sealed class Singleton
    {
        private static int counter = 0;

        //Instance will hold the object and we will
        //return from it
        private static Singleton Instance = null;

        public static Singleton getInstance
        {
            get
            {
                if (Instance == null)
                {
                    Instance = new Singleton();
                }

                return Instance;
            }
        }

        //It ensures that object is not instantiated other than with in the class itself
        private Singleton()
        {
            counter++;
            Console.WriteLine("Singleton object creation number: {0}", counter);
        }

        public void PrintMessage(string message)
        {
            Console.WriteLine(message);
        }
    }
}

So in the above code we have we made the class as sealed also made the constructor as private. As a result object of this class cant be created from outside also this class cant be inherited as a result we need to create the object of this class from this class itself. One more thing when we are creating the object is to check if we have a object present already if so return that. the below code does the object creation

        private static Singleton Instance = null;

        public static Singleton getInstance
        {
            get
            {
                if (Instance == null)
                {
                    Instance = new Singleton();
                }

                return Instance;
            }
        }

The problem with lazy initialization is that the creation of the object is delayed till the invoke of getInstance method. Now this works fine in single threaded environment but if we were in multi-threaded environment this may lead to tread race situation and end with multiple object creation.

The solution to this problem is to use locks.

Singleton implementation: Lazy Initialization (no thread safety)(demo)

using System;
using System.Threading.Tasks;

namespace design_patterns
{
    class Program
    {
        static void Main(string[] args)
        {
            Parallel.Invoke(
                () => Printmsg1(),
                () => Printmsg2());
            
            Console.WriteLine("Hello World!");
            Console.ReadLine();
        }

        private static void Printmsg1()
        {
            Singleton msg1 = Singleton.getInstance;
            msg1.PrintMessage("Design patterns are simple");
        }

        private static void Printmsg2()
        {
            Singleton msg2 = Singleton.getInstance;
            msg2.PrintMessage("If time is spent on it");
        }
    }
}

using System;

namespace design_patterns
{
    //If this class is not sealed it can be inherited
    //from other class (given that class is within this class
    //nested class)
    public sealed class Singleton
    {
        private static int counter = 0;

        private static readonly object objectlock = new object();

        //Instance will hold the object and we will
        //return from it
        private static Singleton Instance = null;

        public static Singleton getInstance
        {
            get
            {
                //Doble Check locking
                if (Instance == null)
                {
                    lock (objectlock)
                    {
                        if (Instance == null)
                        {
                            Instance = new Singleton();
                        }
                    }
                }
                return Instance;
            }
        }

        //It ensures that object is not instantiated other than with in the class itself
        private Singleton()
        {
            counter++;
            Console.WriteLine("Singleton object creation number: {0}", counter);
        }

        public void PrintMessage(string message)
        {
            Console.WriteLine(message);
        }
    }
}

Double Check locking: If one thread is using a code snippet which is enclosed in lock then no other thread can access it till that snippet is freed by that thread. So lets assume if we have null in our instance why to go into the lock for that reason we are checking instance is equal to null for the second time.

Lazy Initialization vs Early Initialization:

If we delay the initialization of the object till the point object is accessed is called a lazy initialization.

Some benefits include:

  1. Performance
  2. Reduce unnecessary computation and complexity of code
  3. Memory foot-print
  4. Quick startup

If we initialize the required object before it’s being accessed is called as Early Initialization.

using System;

namespace design_patterns
{
    //If this class is not sealed it can be inherited
    //from other class (given that class is within this class
    //nested class)
    public sealed class Singleton
    {
        private static int counter = 0;
        
        private static readonly Singleton Instance = new Singleton();

        public static Singleton getInstance
        {
            get
            {
                return Instance;
            }
        }

        //It ensures that object is not instantiated other than with in the class itself
        private Singleton()
        {
            counter++;
            Console.WriteLine("Singleton object creation number: {0}", counter);
        }

        public void PrintMessage(string message)
        {
            Console.WriteLine(message);
        }
    }
}

If you run you will see that getinstance is called twice but in output, only one object creation statement is loaded. Also is this code thread-safe the short answer is that common language runtime will take care of the variable initialization and its thread safety.

private static readonly Singleton Instance = new Singleton();

        public static Singleton getInstance
        {
            get
            {
                return Instance;
            }
        }

So getInstance is returning instance and if we see instance its a new instance of singleton class. How is that on concurrent calls it is not creating new instances. So when we declare a variable (Instance) as readonly. you can only assign value to it ones at the time of its declaration as a result Instance holds instance of the class. Next when we call getInstance we are only getting the value of instance and we cant update the Instance value from outside as setter is not defined.

With .Net 4.0 Lazy Initialization is made Simple

using System;

namespace design_patterns
{
    //If this class is not sealed it can be inherited
    //from other class (given that class is within this class
    //nested class)
    public sealed class Singleton
    {
        private static int counter = 0;
        
        private static readonly Lazy<Singleton> Instance = new Lazy<Singleton>(() => new Singleton());

        public static Singleton getInstance
        {
            get
            {
                return Instance.Value;
            }
        }

        //It ensures that object is not instantiated other than with in the class itself
        private Singleton()
        {
            counter++;
            Console.WriteLine("Singleton object creation number: {0}", counter);
        }

        public void PrintMessage(string message)
        {
            Console.WriteLine(message);
        }
    }
}

Static is a keyword and Singleton is a design pattern
Static classes can contain only static members
Singleton is an object creational pattern with one instance of the class
Singleton can implement interfaces, inherit from other classes and it aligns with the OOPS concepts
Singleton object can be passed as a reference
Singleton supports object disposal
Singleton object is stored on the heap
Singleton objects can be cloned

So lets implement the singleton on our project and see whether the counter issue be fixed

namespace Parkingmanagment
{
    public interface Iparking
    {
        public int SpaceOccupied { get; set; }
        public int TotalSpace { get; set; }

        public void ParkingStatus();

        public void In();
        public void Out();
    }
}
using System;
namespace Parkingmanagment
{
    public sealed class LevelOneParking : Iparking
    {
        private static readonly LevelOneParking Instance = new LevelOneParking();
        public static LevelOneParking getInstance
        {
            get { return Instance;  }
        }
        
        public int SpaceOccupied { get; set; } = 0;
        public int TotalSpace { get; set; } = 1000;

        public void In()
        {
            TotalSpace--;
            SpaceOccupied++;
        }

        public void Out()
        {
            TotalSpace++;
            SpaceOccupied--;
        }

        public void ParkingStatus()
        {
            Console.WriteLine($"Level 1 : TotalCapacity: {TotalSpace} / Occupied: {SpaceOccupied}");
        }

    }
}
using System;

namespace Parkingmanagment
{
    public sealed class LevelTwoParking :Iparking
    {
        private static readonly LevelTwoParking Instance = new LevelTwoParking();
        public static LevelTwoParking getInstance
        {
            get { return Instance; }
        }

        public int SpaceOccupied { get; set; } = 0;
        public int TotalSpace { get; set; } = 1000;

        public void In()
        {
            TotalSpace--;
            SpaceOccupied++;
        }

        public void Out()
        {
            TotalSpace++;
            SpaceOccupied--;
        }

        public void ParkingStatus()
        {
            Console.WriteLine($"Level 2 : TotalCapacity: {TotalSpace} / Occupied: {SpaceOccupied}");
        }
    }
}
namespace Parkingmanagment
{
    public sealed class ParkingLotFactory
    {
        private static readonly ParkingLotFactory Instance = new ParkingLotFactory();

        public static ParkingLotFactory getInstance
        {
            get { return Instance;  }
        }

        public Iparking parkingSelection(string selection)
        {
            int.TryParse(selection, out int sel);
            if (sel <= 2)
                return LevelOneParking.getInstance;
            else
                return LevelTwoParking.getInstance;
        }
    }
}
using System;

namespace Parkingmanagment
{
    public class ParkingClient
    {
        private Iparking iparking;
        private ParkingLotFactory parkingObject;

        public ParkingClient()
        {
            parkingObject = ParkingLotFactory.getInstance;
        }

        public string GetInput()
        {
            Console.WriteLine("Please select your vehicle");
            Console.WriteLine("1 for Bike");
            Console.WriteLine("2 for Car");
            Console.WriteLine("3 for EV");
            Console.WriteLine("4 for Transport");
            string sel =  Console.ReadLine();
            return sel;
        }

        public void AccessParking(string selection)
        {
            iparking = parkingObject.parkingSelection(selection);
        }

        public void ParkingStatus()
        {
            iparking.ParkingStatus();
        }

        public void VehicleIn()
        {
            iparking.In();
        }

        public void VehicleOut()
        {
            iparking.Out();
        }

    }
}
using System;

namespace Parkingmanagment
{
    class Program
    {
        static void Main(string[] args)
        {
            int counter = 1;
            Console.WriteLine("Hello World!");
            Console.WriteLine("You are entering a smart Parting lot");

            ParkingClient PC = new ParkingClient();
            while (counter != 0)
            {
                string Selection = PC.GetInput();
                if (Selection != "failed")
                {
                    PC.AccessParking(Selection);
                    PC.ParkingStatus();
                    PC.VehicleIn();
                    PC.ParkingStatus();
                    Console.WriteLine("Another vehicle to enter press 1 else 0");
                    
                    if(1 != Convert.ToInt32(Console.ReadLine()))
                    {
                        counter = 0;
                    }
                }
            }

        }
    }
}

One thought on “Singleton Pattern

Leave a Reply

Your email address will not be published. Required fields are marked *