top of page
Writer's pictureSunil Kumar Yadav

Singleton: Must Know Design Pattern (3/7)


Image: Singleton Design Pattern (PC: www.refactoring.guru)

Singleton is a part of Gang of Four design pattern and it is categorized under creational design patterns. In this article, we will delve deeper into the utilization of the Singleton pattern. While it is among the simplest design patterns to model, it simultaneously ranks as one of the most contentious patterns due to its complexity in practice.


What is Singleton pattern?

The Singleton Pattern is a design principle that dictates the creation of a class with a solitary instance, ensuring universal accessibility to that instance. Put differently, this pattern mandates that a class guarantees the existence of just one instance, permitting all other classes to utilize this single object.


Image: Singleton in action (PC:www.refactoring.guru)

A singleton class implementation should exhibit the following characteristics:


It must maintain a single instance

This is achieved by creating an instance of the class from within the class itself. Preventing external classes or subclasses from creating their instances is accomplished by marking the constructor as private in languages like C++ and Java. This ensures that no other class can access the constructor and, therefore, cannot create additional instances.


The instance should be globally accessible

The instance of a singleton class should be accessible from any part of the code so that each class can utilize it.


Let's try to understand singleton design patterns with the help of a simple Python example.

class ApplicationState:
    instance = None

    def __init__(self):
        self.isLoggedIn = False

    @staticmethod
    def getAppState():
        if not ApplicationState.instance:
            ApplicationState.instance = ApplicationState()
        return ApplicationState.instance

appState1 = ApplicationState.getAppState()
print(appState1.isLoggedIn)   # False

appState2 = ApplicationState.getAppState()
appState2.isLoggedIn = True

print(appState1.isLoggedIn)   # True
print(appState2.isLoggedIn)   # True

In the above Python example, we've class ApplicationState which has a class attribute named instance to maintain the record of object creation. With the help of the static method getAppState(), the user/client can get the instance i.e. object of class ApplicationState. Each time the user/client tries to create a new instance/object of the class via getAppState() method, the class attribute instance is checked, and if the object is already created then the reference of that object is returned, else new object is returned.


Where Singleton pattern is used?

Singleton pattern is mostly used in multi-threaded and database applications. Below are a few common cases where a singleton pattern is used.

  1. Hardware Interface Access: When dealing with external hardware resources like printers, ensuring only one instance of a class (e.g., a print spooler) handles access can prevent issues related to concurrent access and potential deadlocks.

  2. Logger: For logging utilities, using a Singleton pattern can ensure that log files are generated consistently without conflicts, even when multiple client applications are logging simultaneously.

  3. Configuration File: Managing configuration data as a Singleton can improve performance by loading the data into in-memory objects once and allowing multiple clients to access it concurrently.

  4. Cache: Using the Singleton pattern for a cache ensures that all client applications refer to the same cache instance, reducing redundant data retrieval and improving data consistency.

Pros and Cons

The advantages of Singleton design patterns are

  • Users can be sure that a class has only a single instance.

  • Users gain a global access point to that instance.

  • The singleton object is initialized only when it’s requested for the first time.

The disadvantages of Singleton design patterns are

  • Mixing it with business logic can lead to a violation of the Single Responsibility Principle when this pattern addresses two concerns simultaneously.

  • The Singleton pattern may obscure poor design choices, particularly when program components have excessive mutual knowledge.

  • In a multithreaded environment, handling this pattern is crucial to prevent multiple threads from inadvertently creating multiple instances of a singleton object.

  • Testing the client code of the Singleton can be challenging since numerous testing frameworks depend on inheritance for generating mock objects.

Recent Posts

See All

Comments


bottom of page