Singleton Design Pattern with Java

The problem: Imagine if we always had to create new instances for expensive objects, like DatabaseConnectors or Loggers, and use them in many places in the system. Imagine all the wasted memory. You could easily have a memory leak and your system could not work at all. How can we solve this problem? Is there a way to deal with it? Yes! The Singleton Pattern solves this problem, and the good thing is, it is very simple to implement it!

The diagram:

Logger

Get the source code here: Builder Design Pattern

Yes, only one class – it’s the simplest Pattern in my opinion, but it solves serious problems that can completely compromise your system. I will use a Logger class as an example because every system needs a log, right?

Let’s see in a practical way how to use it!

1 – The Singleton class: The first thing we do is to declare the Logger class as static because we want it to be used in the entire application. Then we must create a private constructor to avoid direct instantiations. We also create the getInstance() method where we finally create the instance of Logger. It’s important to make clear that we are using lazy loading. We first ask if the object was created. If not, we create the instance. Another important thing to mention is that we are synchronizing the creation of the object. This means that we are avoiding concurrency problems. Once we create the instance, we won’t have to create it anymore.

public class Logger {

  private static Logger logger = null;

  private Logger() {
    super();
  }

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

    return logger;
  }
}

2 – The Unitary Test:

Summary of actions:
1 – We created the Singleton class
2 – We declared the static Logger class
3 – We created the getInstance() method using lazy loading

You can try out this test:

public class SingletonTest {

  @Test
  public void verifyIfTheInstancesAreTheSame() {
    Logger firstLog = Logger.getInstance();
    Logger secondLog = Logger.getInstance();
    Logger thirdLog = Logger.getInstance();

    Assert.assertEquals(firstLog, secondLog);
    Assert.assertEquals(secondLog, thirdLog);
  }
}

To practice this Pattern you can create, for example, DatabaseConnector class and make it the Singleton. Then create your Unitary Test to check if the instance is the same. Try to use TDD (Test Driven Development). Start the development from the test.

Written by
Rafael del Nero
Join the discussion