Creational Design Pattern: Singleton

In programming, an object is called singleton if it’s only have a single instance to be used in all your logic code.

Wait, what is an instance?

City jakarta = new City();

Why use Singleton?

To ensure that a class has just a single instance.

To provide a global access point to that instance.

Real-World Analogy

How to apply a Singleton?

  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.

The Singleton Structure

Singleton can be recognized by a static creation method, which returns the same cached object.

It’s Coding Time!

private static City instance = nullstatic City getInstance() { ... }
val tempInstance = instance
if(tempInstance != null) return tempInstance
val newInstance = City()
instance = newInstance
return newInstance

The Singleton Types

1. Early Loading Singleton

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

2. Single-Thread — Lazy Loading Singleton

3. Multi-Thread — Lazy Loading Singleton

// declare volatile annotation
@Volatile

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
}
}

What type of Singleton should I use?

Review Session

Photo by Charles 🇵🇭 on Unsplash
  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.

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.

--

--

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