DEV Community

Cover image for Singleton Design Pattern: #1
Israel-Lopes
Israel-Lopes

Posted on

Singleton Design Pattern: #1

The Singleton design pattern is used to ensure that a class has only one instance for the entire program run and to provide a global point of access to that instance.

There are several situations where the Singleton pattern is useful:

  1. Management of Shared Resources: If you have a resource that needs to be shared by multiple pieces of code, such as a database connection, a log object, or a thread pool, Singleton can ensure that there is only one instance of that resource. resource and that it is globally accessible.

  2. Concurrent Access Control: Singleton can be used to control concurrent access to a shared resource. By having a single instance, you can ensure that concurrent access is coordinated and that operations are performed securely.

  3. Access to global settings or information: If you have global information or settings that need to be accessed from different parts of the program, Singleton can provide a centralized point to access that information.

It is important to keep in mind that the use of the Singleton pattern must be careful, as it can introduce coupling and make the code difficult to test. In addition, it is essential to consider your system's specific requirements and characteristics before deciding to use a Singleton.

In Java, Singleton can be implemented by ensuring that the class has a private constructor, a static method to get the single instance, and a private static variable to hold that instance. In this way, the Singleton can control instance creation and provide global access to the instance.

Let's see an example of its use below:

public class Logger {
    private static Logger instance;

    private Logger() {
        // logger initialization
    }

    public static Logger getInstance() {
        if (instance == null) {
            synchronized (Logger.class) {
                if (instance == null) {
                    instance = new Logger();
                }
            }
        }
        return instance;
    }

    public void log(String message) {
        // Lógica para registrar o log
        System.out.println("Log: " + message);
    }
}

Enter fullscreen mode Exit fullscreen mode

In this example, the "Logger" class implements the Singleton pattern to ensure that only one logger instance is created during program execution.

You can use it as follows in your code:

Logger logger = Logger.getInstance();
logger.log("log message");
Enter fullscreen mode Exit fullscreen mode

That way you get the single instance of the logger and you can call the "log" method to record your log messages.

The Singleton pattern is commonly used in scenarios where you need a single shared instance of a class across the entire application. The above "Logger" example is just an illustrative example, but you can find the Singleton pattern being used in many libraries and frameworks to provide global access to resources such as database connection pools, caches, settings, etc.

└─ Main
   └─ main(String[] args)
      └─ Logger
         ├─ instance: Logger
         └─ getInstance(): Logger
            └─ instance: Logger
               └─ new Logger()
Enter fullscreen mode Exit fullscreen mode

In this example, we have the Main class with the main method as the root node. Inside the main method, the Logger class is used.

The structure of the Singleton pattern is represented by the following elements:

  • Logger is the class that implements Singleton.
  • instance is a static attribute of the Logger class that represents the single instance of the class.
  • getInstance() is the static method of the Logger class which is responsible for returning the existing instance or creating a new one, if necessary.
  • When the getInstance() method is called for the first time, a new instance of the Logger class is created and assigned to instance. In subsequent calls to getInstance(), the existing instance is returned.
public class Logger {
    private static Logger instance;

    private Logger() {
        // logger initialization
    }

    public static Logger getInstance() {
        if (instance == null) {
            synchronized (Logger.class) {
                if (instance == null) {
                    instance = new Logger();
                }
            }
        }
        return instance;
    }

    public void log(String message) {
        // Lógica para registrar o log
        System.out.println("Log: " + message);
    }
}

public class Main {
    public static void main(String[] args) {
        Logger logger = Logger.getInstance();
        logger.log("log message");
    }
}

Enter fullscreen mode Exit fullscreen mode

____________________<< go to back__________________

Texto alternativo da imagem

Top comments (0)