Tech Point Fundamentals

Sunday, January 30, 2022

Singleton Design Pattern | Singleton Anti-Pattern

Singleton Design Pattern | Singleton Anti-Pattern

singleton-design-pattern

Singleton Pattern is a topic that is asked in each and every interview.  One more interesting question i.e. static class vs singleton is also very common in the interview. Apart from this singleton object vs transient object vs scoped object in the Dependency Injection is also very frequent in the interview. In this article, we will walk through some more interesting facts and interview questions, and answers based on the singleton.

Watch our videos here




Introduction


Singleton pattern is a Creational Pattern of Gang of Four (GoF) Design Patterns. It ensures that one and only one persistent object exists and has a single point of access to it.


The best thing about singleton is that it can be implemented lazily and can be used in a multi-threaded environment as well.


Before going forward to the singleton pattern let's understand the Creational Pattern first.




Creational Design Pattern


The creational design patterns are design patterns that deal with object creation and instantiation mechanisms. This pattern helps us to centralize the object creation logic and depending upon the condition, it will create, initialize, and return the appropriate object to the client.


The creational design patterns are basically two types:


1. Object Creational Pattern: This pattern deals only with object creation and instantiation.

2. Class Creational Pattern: This pattern deals with class instantiation.




Examples of Creational Design Patterns


  1. Singleton Design Pattern
  2. Factory Design Pattern
  3. Abstract Factory Design Pattern
  4. Builder Design Pattern
  5. Prototype Design Pattern
  6. Fluent Interface Design Pattern




Singleton Design Pattern


The Singleton Pattern was originally introduced in the famous book "Design Patterns: Elements of Reusable Object-Oriented Software" of "Gang of Four" by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. 

According to the GoF:

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


The singleton design pattern helps you to ensure that a class has one and only one instance available throughout the application runtime and provides a global way to access them.


The singleton design pattern restricts the instantiation of a class to one "single" instance that's why the name singleton. The term comes from the mathematical concept of a singleton.


Singleton is a design pattern and it is language-independent, so it applies to several languages C#, JAVA, C++, etc.




Types of Singleton Pattern


There are two forms of the singleton design pattern based on loading and instantiation and both have their own pros and cons:


1. Early or Eager Instantiation: In this type of singleton the instance is created at load time.

2. Lazy Instantiation: In this type of singleton the instance is created only when required. 


Again based on the environment singleton can be of two different flavors and both have their own advantages and disadvantages:


1. Thread-Safe Singleton: This type of singleton makes sure that one and only one instance is created in a multi-threaded environment as well.

2. Non-Thread Safe Singleton: This type of singleton does not guarantee that one and only one instance is created in a multi-threaded environment.


However, you can combine both the features i.e. lazy loaded and thread-safe in a single singleton based on your requirement.

 



Why Singleton?


The singleton design pattern solves the object creation problem. The singleton implementation:


  1. Ensures that the singleton class has one and only one instance.
  2. Controls its instantiation.
  3. Restricts the number of instances.
  4. Provide easy access to the sole instance of the class.



Fundamental Anatomy of  Singleton Design Pattern


Though there are various ways of implementing the singleton pattern, all of them should have the following four characteristics:

1. Sealed or Final Class:

The sealed class (in C#) or final class (in Java) prevents the singleton class from inheriting or extending by any class including internal  (nested) or external class. Please read more about the sealed class here.

2. Private Default Constructor:

The private parameterless constructor prevents the singleton class from instantiation by any external classPlease read more about the private constructor here.

3. Private Static Variable:

The private static variable holds the reference of the created singleton instance. The static modifier allows it to allocate memory only once.

4. Public Static Method or Property:

This public static method or property provides the global point of access to the singleton object and returns the singleton instance to the callerPlease read more about the static methods and properties here.






Why Singleton Class Sealed or Final?


If a private default constructor prevents the subclassing then why the class should be sealed or final?

So there are two reasons and both are to prevent subclassing or inheritance. 

1. If you define only the default private constructor, it prevents both instantiation and subclassing but if any developer creates any public constructor accidentally other classes can instantiate and extend both. Which is a violation of the singleton design pattern.

2. The private default constructor cannot prevent the nested class (inner class) of the singleton from extending. Which is a violation of the singleton design pattern again.

So they can cause a trivial problem to the singleton design pattern goal. That's why we should make the singleton class sealed. 

Please read more about the sealed class here and the private constructor here.



Singleton vs Global Variable


Singleton ensures that a class has only one instance at any moment of time. It provides a global access point to that instance to the clients.

The global variables are very handy but they are very unsafe as well because any code can potentially overwrite the contents of those variables and crash the application.

Just like the global variable singleton also allows you to access its object from anywhere in the program but it protects that instance from being overwritten by other code. Also, it supports lazy loading.




Is Destructor allowed in Singleton Class?


Unlike the static classes, the singleton class can have the destructor.  So the question is if the purpose of a singleton is to provide a single instance throughout the application then why do we need a destructor in a singleton?

A destructor is called from within the class scope, where it is accessible when the program exits. In C# all classes have a destructor. If you don't create one the compiler will do so for you implicitly.

You can define a destructor or dispose method explicitly in a singleton class, but it is a good idea to make it private. If you make it private then any client code won't call the destructor accidentally. As calling the destructor would cause the singleton to fail for all clients as the instance would become invalid. Deleting a singleton instance is a non-trivial design problem.

Please read more about the destructor here. and IDisposable Interface here.



Singleton Pattern vs Singleton Object: DI and IoC


Different IoC containers like Autofac, Ninject, etc also control the lifetime and scope of a registered object for example singleton (one instance for the duration of the application), transient (new instance each time), or scoped (one instance per scope).

So here we are not creating any singleton pattern explicitly, everything is taken care of by the IoC container. We can still use the singleton object in our project and in fact, everyone has used these in the projects.

Please read more about DI and IoC here.



Singleton Class vs Static Class


Why this question is asked in the interview? So to understand this first we have to know the similarities between singleton class and static class:

  1. Both the static class and singleton class have one and only one instance throughout the whole application. 
  2. Both are used for having the global state and accessibility.
  3. Both provide thread safety as well.
  4. Singleton uses static methods or properties and static variables for the singleton implementation. We know that if any class or any class member is declared as static then that class or member would not be collected by GC. 
  5. Both singleton instance and static classes cannot be garbage collected because they are not stored in the stack, they are stored in a high-frequency heap which is beyond the scope of the garbage collector. On the other hand, since the singleton uses the static variable and static property for holding the object reference, it cannot be collected by the garbage collector as well. So both get destroyed only when the corresponding process or app domain gets unloaded from the memory.
  6. Both can be cloned very easily.



Now let's see the difference between singleton class vs static class:

  1. Singleton is a pattern not a keyword like static. So for creating a static class static keyword is sufficient while in the case of a singleton, there is a need to write the logic for the singleton.
  2. Singleton class must have a private default instance constructor while a static class cannot contain any instance constructor.
  3. A static class is neither instantiated nor extended while a singleton class can be.
  4. A static class is sealed implicitly but the singleton class must be decorated as sealed explicitly.
  5.  A singleton can implement the interface or inherit from another class but the static class neither implements the interface nor extends from any other class.
  6. We cannot implement the dependency injection with a static class but DI is possible with the singleton class because it can be interface driven.
  7. The scope of the static class is at the app domain level because it is managed by the CLR while the scope of the singleton object is across the application lifecycle.
  8. A static class cannot have any destructor but a singleton class can define a destructor.
  9. The singleton class instance can be passed as a parameter to another method while a static class cannot be because it contains only static members.

Please read more about the static class here and static class interview questions and answers here.



Singleton Pattern vs Factory Pattern


The singleton design pattern uses a special form of the factory design pattern to ensure that only one instance of an object is ever created. However:

  1. Singleton does not allow any parameter to be passed usually while a factory pattern allows a parameter to be passed.
  2. A singleton pattern ensures that you always get back the same instance, whereas the factory pattern generally returns a new instance of one of several possible classes depending on what parameters are actually passed by the consumer.



Singleton Pattern vs Prototype Pattern


  1. The prototype pattern is very unique in the creational design pattern. It does not require any class, it needs only the object. While singleton requires a class to implement a singleton.
  2. Singleton pattern deals with the object creation while the prototype pattern deals with cloning the object.
  3. Prototype pattern allows us to create an object from the existing instance of the object while the purpose of the singleton is to ensure that one and only one instance of the class is created.

Please read more interview questions based on design patterns and principles here.



Why Singleton is an Anti-Pattern?


The singleton pattern is called an anti-pattern. It is also known as singletons evil or pathological liars. Some of the best-known reasons behind this are as follows:


1. Only Assumption

The biggest problem with the singleton pattern is based on only an assumption. In the singleton pattern, there is an object for which there is an assumption that there will only ever be one instance at any moment. But no guidelines about how it should be implemented.

But anyone can simply construct only a single instance of the object and no other instances, doing so is not the singleton pattern, though there is only one instance.

In singleton, anybody can clone the singleton object in different ways in different languages. To prevent this the singleton class has to take care of the necessary implementation also apart from the singleton logic.




2. Vague Definition
    
"Ensure a class has one instance, and provide a global point of access to it."

The definition of a singleton is vague in itself which causes difficulties in discussing singleton. The definition is only meaningful if it has some state, without that ensuring there is only ever one object of a particular class is meaningless.

Generally, a pattern or principle should have specific rules or guidelines which must be followed for example SOLID Design Principles where each and every principle has a specific rule which must be adhered to while implementing.

But in the case of singleton, there is no rule for implementation. There are different ways to implement and instantiate the singleton, everybody is using their own choice and comfort. So by telling the singleton nobody can judge how the singleton is implemented.




3. SOLID's Single Responsibility Principles Violation

The singleton design pattern also violates the Single Responsibility Principle of SOLID because it is not only responsible for the singleton's normal task but the instantiation and prevention of the cloning as well. Please read more about the Single Responsibility Principle here.


4. Design Models Violation

In OOPS an object's knowledge of the outside world should extend to what it is told via its interface.  The purpose of an object is to provide certain functionality to its clients, and an object should provide the minimum useful interface that makes this functionality accessible. 

An interface can't make any assumptions about how many objects that support that interface are needed, because that issue is resolvable only in the outside world.  And singleton says that there can only ever be one object of a certain class. So the singleton underpins modularity by putting an interface and the management of its instance in one place.



5. OOP'S Encapsulation Violation

Encapsulation is one of the fundamental pillars of object-oriented design. Encapsulation is a protective layer that prevents the data from being accessed by the code outside this shield. So it draws a boundary.  

As we know the global variables have been known to be the enemy of encapsulation and singletons are basically used as global variables. Singleton has one instance, and it penetrates the scopes in which it is used via a route other than the public interface, making it the operational equivalent of a global variable. Hence the singleton has the same drawbacks as global variables.


6. Unit Testing Problem

Singletons are difficult to test because they carry a global state for the duration of the program. 




Singleton Object Cloning and Preventions


The whole purpose of a singleton is to control the object creation and restrict the number of objects to only one. However, the singleton object can be cloned very easily and that is a violation of the singleton pattern. 

Swallow Cloning vs Deep Cloning


There are two types of object cloning, shallow cloning, and deep cloning. The shallow cloning only copies the reference, not the referenced objects in the class. On the other hand, deep cloning copies the referenced objects as well. i.e 

A shallow copy copies only the elements, whether they are reference types or value types, but it does not copy the objects that the references refer to. The references in the new cloned object point to the same objects that the references in the original object point to. While a deep copy of an object copies the elements and everything directly or indirectly referenced by the elements.


So in C# the shallow copy or clone means that value types of class are duplicated, but reference types are not. However, in deep cloning, both value types and reference types are duplicated. The MemberwiseClone() method in C# creates a shallow copy.


There are multiple ways to break the singleton property of a class. So let's see some ways of cloning the singleton object and their preventions.



1. Cloning using Clone() Method


In Java, the Clone() method of the Object class is used for cloning. It is a protected method and every class in Java is extended from this the Object class implicitly. So it is there for the singleton class as well.

But for cloning the class must implement the Cloneable interface, otherwise, the Clone() method generates CloneNotSupportedException

So if you have not implemented the Cloneable interface in the Singleton class, then it does not require writing any logic to prevent cloning in the singleton

But there is a problem if the singleton class is inheriting from a class that has implemented a Cloneable interface. In that case, to prevent cloning the singleton class must need to override the clone() method inside the Singleton class and throw CloneNotSupportedException explicitly. However, this is only necessary if a parent of a singleton class has implemented a public clone() method.

There is one more problem here is if the parent class has already overridden the clone() method without throwing CloneNotSupportedException. Since CloneNotSupportedException is a checked exception and if a parent class method is not throwing CloneNotSupportedException, we cannot throw it from any child class including our Singleton. Doing so will cause a compile-time error. So in that case, the singleton class should throw a new RunTimeException instead of CloneNotSupportedException.



2. Cloning using Reflection


Reflection is used to examine or modify the behavior of methods, classes, and interfaces at runtime. So using reflection we can create multiple objects of singleton class in Java

There are multiple ways to prevent the singleton pattern from Reflection Cloning, but one of the best solutions is to throw a run time exception in the constructor if the instance already exists. By doing so nobody would be able to create a second instance.

3. Cloning using Binary Serialization


By doing serialization we can save the object into a file as a byte stream or send it over a network. When anyone serializes a singleton object and then again deserializes that object, it will create a new instance. Hence the deserialization violates the singleton pattern.

To prevent singleton object cloning via serialization, the singleton class needs to override the readResolve() method and return the same Singleton instance from there.

Similarly in C# for cloning one can use MemberwiseClone(), ICloneable Interface, Manual Deep Cloning, Binary Serializer Cloning, or JSON Serializer Cloning.



What is Enum Singleton?


Enum is a good choice for implementing the singleton. We know that the reflection can break the singleton by cloning the singleton object. So in the case of complex singleton, preventing the reflection attach one can use an enum.

The reason behind this is that in Java the enum values are instantiated only once. We cannot invoke the enum constructor explicitly from the program in Java same as a static constructor in C#. JVM handles the creation and invocation of enum constructors internally.

Since the enum constructor cannot be called explicitly, it is also inaccessible by reflection as well. Therefore, reflection can’t break singleton property in the case of enums.

On the other hand, it cannot be broken using serialization attacks as well. Enums are thread-safe also by default. The only problem with the enum singleton in Java is that it is not lazy-loaded.



Static Constructor vs Static Type Initializer in Singleton


Some implementations of the singleton pattern use a static constructor. In C# a static constructor executes at most once in a given application domain

In C# you can initialize the static field directly with a declaration as well. The instantiation does occur when public property or method is called the first time, so it is some sort of lazy instantiation.

private static readonly Singleton _instance = new Singleton();


But if you want some kind of pre-processing logic, you can use a static constructor.

private static readonly Singleton _instance;
static Singleton()
{
instance = new Singleton()
 }

Both the above implementations will work in multi-threaded environments as well so you have nothing to do with it because everything is taken care of by the .NET Framework itself. Please find the complete singleton implementation in the last of the article.

But the above two implementations are not the same actually. In the case of the first direct initialization where we have no static constructor will be marked as "beforefieldinit" flag by the compiler, which means its type initializer is invoked at any time before the first reference to a static field in it. 

But if you define a blank static constructor in the first implementation, both will be identical technically, in terms of initialization. The "beforefieldinit" flag has a strange effect, in that it cannot only mean that a type initializer is invoked earlier than that of an equivalent type without the flag, but it could also even be invoked later, or not at all.

Please read more about the static constructor here and the static class here.



Use of Singleton Pattern


  1. Singleton class can be used for the Dependency Injection to inject the dependent singleton object.
  2. Singleton objects are preferred over the global variables as singleton has fewer flaws compared to the global variable.
  3. Singletons are mostly used to share the common global data across the application for example logger, configuration data, database connection, etc.
  4. The factory pattern, builder pattern, and prototype patterns can also use a singleton.
  5.  Singleton is also suitable for Facade objects and service proxies



Advantages of Singleton Pattern


  1. Singleton patterns can be lazy-loaded only when required.
  2. Singleton provides the single point of access for the singleton instance.
  3. Singleton reduces the overhead of instantiating a heavy object again and again.
  4. Singleton is memory efficient also as it holds only a single memory reference.
  5. Singleton can implement an interface so it is useful in the case of DI.

Disadvantages of Singleton Pattern


  1. Unit Testing is very difficult in singleton as it represents the global state in the application.
  2. Singleton is an anti-pattern.
  3. Singleton needs special treatment for the multi-threaded environment.
  4. Singleton also needs special and extra logic to prevent cloning.
  5. Singleton carries almost all the flaws of a global variable.



Singleton Pattern Implementations


As there is no rule or way defined in the Singleton Definition by GoF, there are multiple ways to implement the singleton pattern based on the environment (normal vs multi-thread) and need (lazy vs eager loading). 

For implementing the singleton there are different things in the different languages as well and every implementation has its own pros and cons. Let's see some implementations in the .Net.

In all the implementations of singleton here we are using the public static property for exposing the singleton instance to the client or user, but you can use the public static method as well instead of property.

We have already seen the non-thread-safe version of the singleton at the beginning of this article. Let's see the thread-safe version and lazy-loaded versions of the singleton.




Thread Safe Singleton using Lock


This is the most common, easy, and simple thread-safe singleton implementation which can be implemented in almost all programming languages. In this implementation, we use a lock on a shared object and then check whether the instance is created or not. 

But, the problem with this implementation is performance because performance suffers since a lock is required every time an instance is requested.


public sealed class Singleton
{
	private static Singleton _instance = null;
	private static readonly object padlock = new object();

	private Singleton()
	{
	}

	public static Singleton Instance
	{
		get
		{
			lock (padlock)
			{
				if (_instance == null)
				{
					_instance = new Singleton();
				}
				return _instance;
			}
		}
	}
}



Thread Safe Singleton using Double Check Lock


This is not a very common way of singleton implementation as it is not supported by many languages like Java. Compared to previous thread-safe implementations it does not require taking out a lock every time.


public sealed class Singleton
{
	private static Singleton _instance = null;
	private static readonly object padlock = new object();

	private Singleton()
	{
	}

	public static Singleton Instance
	{
		get
		{
			if (_instance == null)
			{
				lock (padlock)
				{
					if (_instance == null)
					{
						_instance = new Singleton();
					}
				}
			}
			return _instance;
		}
	}
}



Singleton using Lazy<T> Type


Microsoft has introduced the Lazy<T> type in the .NET 4. So in C#, we can use this to implement the lazy-loaded singleton very easily. The code below implicitly uses LazyThreadSafetyMode.ExecutionAndPublication as the thread-safety mode for the Lazy<Singleton>. You can use other modes as well, based on the requirement.


public sealed class Singleton
{
	private Singleton()
	{
	}

	private static readonly Lazy <Singleton> _lazy =
		new Lazy<Singleton>(() => new Singleton());

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



Singleton using Nested Class

In this implementation, we use a private nested class that creates the singleton instance. This is a fully lazy implementation of a singleton.


public sealed class Singleton
{
	private Singleton()
	{
	}

	public static Singleton Instance
	{
		get 
        {
			return Nested._instance;
		}
	}

	private class Nested
	{                
		static Nested()
		{
		}

		internal static readonly Singleton _instance = new Singleton();
	}
}





Singleton using Static Constructor


We use a static constructor in this version of the singleton. A static constructor executes only once per Application Domain. It does not have any extra overheads for handling the multi-threading issue but the problem with this approach is that it is not lazy-loaded.


public sealed class Singleton
{
	private static readonly Singleton _instance = null;
	
	static Singleton()
	{
		_instance = new Singleton();
	}

	private Singleton()
	{               
	}

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



Conclusion


Singleton is an anti-pattern. There are multiple versions of a singleton, one can use based on their requirement. Also, the purpose of static class and singleton class is different. Singleton patterns and singleton objects are two different things.


No comments:

Post a Comment

Please do not enter any HTML. JavaScript or spam link in the comment box.