Creational Design Pattern: Singleton

Singleton is one of the design patterns in the creational classification. This pattern lets you ensure that a class has only one instance while providing a global access point to this instance.

This is useful when exactly one object is needed to coordinate actions across the system. The term comes from the mathematical concept of a singleton:

Wait, what is an instance?

For a beginner, you may still don’t know the meaning of an instance.
Quoted from Wikipedia,

In object-oriented programming (OOP), an instance is a concrete occurrence of any object, existing usually during the runtime of a computer program.

To make it simple, look at the Java code below.

City jakarta = new City();

This means that we will create an instance of object City, and save it to variable jakarta. The new keyword in Java is used to create a new instance of an object. Now we can conclude that jakarta is an instance of a City.

“But, the description in the first paragraph says that Singleton has only a single instance with a global access point. What does it mean? How to implement it?”

Hold on folks, I’ll explain that later. Let’s start with the benefit of Singleton.

Why use Singleton?

The Singleton pattern solves two problems at the same time, violating the Single Responsibility Principle:

To ensure that a class has just a single instance.

Why would anyone want to control how many instances a class has? The most common reason for this is to control access to some shared resource — for example, a database or a file.

Here’s how it works: imagine that you created an object, but after a while decided to create a new one. Instead of receiving a fresh object, you’ll get the one you already created.

Note that this behavior is impossible to implement with a regular constructor since a constructor call must always return a new object by design.

To provide a global access point to that instance.

Remember those global variables that you used to store some essential objects? While they’re very handy, they’re also very unsafe since any code can potentially overwrite the contents of those variables and crash the app.

Just like a global variable, the Singleton pattern lets you access some object from anywhere in the program. However, it also protects that instance from being overwritten by other code.

There’s another side to this problem: you don’t want the code that solves problem #1 to be scattered all over your program. It’s much better to have it within one class, especially if the rest of your code already depends on it.

Nowadays, the Singleton pattern has become so popular that people may call something a singleton even if it solves just one of the listed problems.

Real-World Analogy

The government is an excellent example of the Singleton pattern. A country can have only one official government. Regardless of the personal identities of the individuals who form governments, the title, “The Government of Jakarta”, is a global point of access that identifies the group of people in charge, which is Jakarta.

How to apply a Singleton?

In an abstract explanation, you only need two simple steps to create a singleton object.

  1. Make the default constructor private, to prevent other objects from using the new operator with the Singleton class. Why? because we need to restrict the object to have a single instance only.
  2. Create a static creation method that acts as a constructor. Under the hood, this method calls the private constructor to create an object and saves it in a static field. All following calls to this method return the cached object.

“What is the second point means? I don’t get it.”
It’s okay, I will show you the example code later.

The Singleton Structure

The point of that structure is the client only can get the instance of your Singleton by calling getInstance(). This function will check the current instance. If it’s null, then we will initialize a new instance and return it, if it isn’t null, just return the instance. Simple yet useful.

It’s Coding Time!

Let’s try to create a Singleton class using Kotlin language.

The above code is a City class with singleton implementation. Let’s breakdown the code and review it.

After the class name, there is a private constructor () declaration. This is a declaration in Kotlin to make the constructor private. We need this to restrict other class from creating a new instance when calling the constructor.

If you force to call City() or in Java equal to new City() to make a new instance, you will get an error because there is no constructor available for the public.

The string name and integer population is a global variable that we will use later to save information to our City instance.

After the global variable declaration, as you can see there is a companion object block. This block is used in Kotlin to declare that any objects or methods inside this block are treated as static. In Java, you would write each of your objects or methods with static as follow:

private static City instance = nullstatic City getInstance() { ... }

And finally, inside the getInstance() method, we need to check the current instance’s condition. If it isn’t null, just return the instance,

val tempInstance = instance
if(tempInstance != null) return tempInstance

but if the instance is null, we will create a new instance (cache it) and then return it.

val newInstance = City()
instance = newInstance
return newInstance

The code inside our getInstance() method is called “lazy initialization” because we only initialize the instance when the client is calling this method. Otherwise, the instance will remain null, not applied to memory.

Our singleton class is done, let’s play with it.
Create a class named Main to test our City singleton.

Because our City class is a singleton, it only shares a single instance among the other. And only the last change to properties are applied.

From the above code, we can say that cityA and cityB are using the same City instance.

The Singleton Types

There are 3 types of singleton.

1. Early Loading Singleton

Singleton that its instance is initialized directly during the instance declaration.

val instance: City = City() // declare the instance directlyfun getInstance(): City { return instance }

2. Single-Thread — Lazy Loading Singleton

Singleton that its instance is initialized only when the Singleton Class is used for the first time only supports a single thread. This is the type of singleton that we make before.

3. Multi-Thread — Lazy Loading Singleton

Singleton that its instance is initialized only when the Singleton Class is used for the first time, supports multi-threaded environment.

In a multi-threaded environment, it is a possible situation that two threads might enter the getInstance() method at the same time, which could create two instances of Singleton class which is not desirable and might make the program behavior unpredictable. To make the creation of Singleton instance thread-safe, the method getInstance() is synchronized so that the method is executed by only one thread at a time.

Overall the declaration is the same as the Single Thread — Lazy Loading Singleton, but we need to declare volatile to an instance variable, and synchronized keyword inside our getInstance() method.

// declare volatile annotation

private var instance: City? = null
fun getInstance() : City {
val tempInstance = instance
if(tempInstance != null) return tempInstance
// declare synchronized block
synchronized(this) {
val newInstance = City()
instance = newInstance
return newInstance

Why do we need to declare volatile to instance variable? because this will help to get the latest updated copy every time, as it will read from the main memory than in its CPU-cache area.

Why do we need to declare synchronized in our getInstance() method? we do this to make the creation of Singleton instance is thread-safe. The method getInstance() is synchronized so that the method is executed by only one thread at a time.

What type of Singleton should I use?

This question is based on your problem and needs. If you just need a simple singleton and don’t give a fu*k about performance, just use the Early Loading Singleton.

If you care about performance, but only use a single threading, use the Single Thread — Lazy Loading Singleton.. *please make sure that you only call getInstance() in a single thread, otherwise your singleton will be initialized twice, results in a multi-instance (and we can’t call this a singleton anymore).

And the last, if you care about performance and using a multi-thread environment, use the Multi-Thread — Lazy Loading Singleton

Review Session

Photo by Charles 🇵🇭 on Unsplash

After all of that theory and code practice, we can conclude that implementing a singleton is simple as:

  1. Add a private static field to the class for storing the singleton instance.
  2. Declare a public static creation method for getting the singleton instance.
  3. Implement “lazy initialization” inside the static method. It should create a new object on its first call and put it into the static field. The method should always return that instance on all subsequent calls.
  4. Make the constructor of the class private. The static method of the class will still be able to call the constructor, but not the other objects.
  5. Go over the client code and replace all direct calls to the singleton’s constructor with calls to its static creation method.

Maybe you want to say,
“Okay, I got the theory. But why do I need Singleton?. When will I need it?. Is it worth to apply this kind of pattern?.”

When to use Singleton?

  • Use the Singleton pattern when a class in your program should have just a single instance available to all clients. For example, a single database object shared by different parts of the program.
  • Use the Singleton pattern when you need stricter control over global variables.

The Pros

  • You can be sure that a class has only a single instance.
  • You gain a global access point to that instance.
  • The singleton object is initialized only when it’s requested for the first time.

The Cons

  • Violates the Single Responsibility Principle. The pattern solves two problems at the time.
  • The Singleton pattern can mask bad design, for instance, when the components of the program know too much about each other.
  • The pattern requires special treatment in a multi-threaded environment so that multiple threads won’t create a singleton object several times. (using Multi-Thread — Lazy Load Singleton)

Relation with other patterns

  • A Facade class can often be transformed into a Singleton since a single facade object is sufficient in most cases.
  • Flyweight would resemble Singleton if you somehow managed to reduce all shared states of the objects to just one flyweight object.
  • Abstract Factories, Builders and Prototypes can all be implemented as Singletons.

“An idiot admires complexity. A genius admires simplicity.” — Terry A Davis

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store