Home Design Pattern - Singleton
Post
Cancel

Design Pattern - Singleton

What is Singleton design pattern?

In a previous blog post, I introduced Builder design pattern. Today, let’s learn another design pattern: Singleton. Both Singleton and Builder are considered Creational design patterns. There are typically 3 types of design pattern: Creational design pattern, Structural design pattern and Behaviour design pattern. Creational design patterns are all about class instantiation. For example, Builder design pattern benefits the instantiation of a complicated class with multiple parameters where some of them are even optional.

Singleton design pattern benefits the instantiation of a class which can be used over and over again. It makes sure a class only has one object and provide a global point of access to it. One use case is Logger class. To log the application, Logger instance is injected to multiple classes that need logging. Singleton design pattern can provent us creating multiple instances of the Logger class. Instead, we create only one Logger instance and use it where it is needed. Clearly, one advantage of Singleton design pattern is to save memory and avoid creating unnecessary mutilple instances.

Implementation in Java

To implement Singleton design pattern in Java, here are 2 ways: Eager and Lazy. Both end up with creating one single instance for a class.

Eager instantiation

The first implementation is eager instantiation, where instance is always created during class loading.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SingletonEager {
  // Create an instance
  private static final SingletonEager INSTANCE = new SingletonEager();

  // Make constructor private, so it cannot be instantiated from outside class
  private SingletonEager() {}

  // Create a static getInstance method
  public static SingletonEager getInstance() {
    return INSTANCE;
  }

  public void printOK() {
    System.out.println("OK!");
  }
}

Then we can access the Singleton instance by

1
SingletonEager singletonEager = SingletonEager.getInstance();

This method is easy to implement. However, one concern of using this method is resource wastage, because the instance is always created, whether it is required or not.

Lazy instantiation

The second implementation is lazy instantiation, where instance is created only when it is called.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class SingletonLazy {
  // Declare a static instance
  private static SingletonLazy INSTANCE;

  // Make constructor private, so it cannot be instantiated from outside class
  private SingletonLazy() {}

  // Create a static getInstance method
  public static SingletonLazy getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new SingletonLazy();
    }
    return INSTANCE;
  }

  public void printOK() {
    System.out.println("OK!");
  }
}

This method can avoid resource wastage, because the instance is only created when getInstance is called. However, this method is workable in single-thread situation. This causes a problem in multi-thread situation where INSTANCE happens to be created in more than one thread in the same time.

To fix this problem, we can use synchronized keyword to make this creation operation atomic. But it potentially impact the performance by increasing waiting time of threads.

1
2
3
4
5
6
public synchronized static SingletonLazy getInstance() {
  if (INSTANCE == null) {
      INSTANCE = new SingletonLazy();
  }
  return INSTANCE;
}

Conclusion

Based on pros and cons listed above, you can choose which one is better for your use case.

This post is licensed under CC BY 4.0 by the author.

Make Bash Terminal Prettier

Design Pattern - Factory

Comments powered by Disqus.