Explaining the Singleton Design Pattern — In Under 5 Minutes!

Explaining the Singleton Design Pattern — In Under 5 Minutes!

This is another quick guide to mastering a?commonly used design pattern, the Singleton. This pattern is one of the most straightforward but controversial patterns in programming. It has many pros and cons. This is one reason why it’s widespread in?programming interviews.

The?singleton design pattern?is classified as a?creational pattern?— a set of rules used to create objects. Specifically, it’s about how to use inheritance or delegation effectively when creating classes or objects.

In mathematics, a singleton is defined as “a set that contains exactly one element”. This pattern is easy to understand and implement since it requires only a few lines of code and is relatively straightforward. Furthermore, a singleton can ensure that there is?only one?class instance and?provide global access. For example, we can only have one active CEO for a company; therefore, the CEO could be represented with a singleton pattern.

Step 1 — Keywords

Defining keywords is the secret recipe in this series of quick guides. This method helped me understand the?design patterns, hardcode them in my mind, and comprehend their differences.

Let’s take a look at the very basics of coding. If you feel comfortable with the terms, skip this step.

  1. An instance is a concrete occurrence of any object. Instances usually exist during a computer program’s runtime and help you to identify distinct entities. For example, class instances are created from classes by subroutines like constructors/destructors.
  2. Private constructors are used in classes that contain static members only. If a class has one or more private constructors and no public constructors, then other classes (except nested classes) are not allowed to create instances of this class.
  3. When we declare a member of a class as static, it means that the static member exists one time for each class, no matter how many objects of the class are created.
  4. Static functions can be called even if no objects of the class exist.

Step 2 — Diagram

No alt text provided for this image
In?software engineering, the?singleton pattern?is a?software design pattern?that restricts the?instantiation?of a?class?to a singular instance. One of the well-known?“Gang of Four” design patterns, which describe how to solve recurring problems in?object-oriented software,[1]?the pattern is useful when exactly one object is needed to coordinate actions across a system.?https://en.wikipedia.org/wiki/Singleton_pattern

To make a class Singleton, there are two programming tricks. Other than that, it is pretty trivial.

Reading from top to bottom:

  • A static(underlined) and private(-) instance of the class
  • A private constructor.
  • A public(+) and static function that returns the instance.

The rule of thumb is that class definitions shouldn’t be more than?7–8 lines of code, no matter which programming language you’re working in.

Step 3 — Code by example

I suggest copying the code from the snippets here and pasting it into an?online C++ editor?like?c++shell,?jdoodle, or?onlineGDB, then running it to observe the?output. Then read the comments or description below.

Class definition

#include <iostream>

class Singleton {
  public: static Singleton *getInstance();
  private: Singleton(){}
  static Singleton* s_instance;
};        

Now we move on to the declaration of the?getInstance()?method and the static data member (variable) outside the class definition. Different ways of writing the getInstance function exist, but I chose the one shown in the snippet below for simplicity. If an instance does not already exist, instantiate one; if you already have an instance,?return it!

Singleton* Singleton::s_instance = 0;Singleton*
Singleton::getInstance()
{
  if(!s_instance)
  {
    s_instance = new Singleton();
    std::cout << "There is no instance, so we created one!\n";
    return s_instance;
  }
  else
  {
    std::cout << "This is the same instance!\n"; return s_instance;
  }
}        

Main function

The primary function acts as the?client. The client cannot create another Singleton class instance and must?use the existing one. This can be verified by the output as well.

int main()
{
  Singleton *singlA = Singleton::getInstance();
  Singleton *singlB = Singleton::getInstance();
  return 0;
}

// Output
// There is no instance, so we created one!
// This is the same instance!        

The?Singleton pattern?has some benefits. For example, other design patterns like?Abstract Factory?and?Facade?can use the Singleton pattern (usually only one Facade object is required). However, as I mentioned in the first paragraph, the Singleton pattern is quite?controversial, and that’s why it’s commonly asked as an?interview question: “What is wrong with the Singleton pattern?

Anti-pattern

I will summarise the reasons why most people consider?Singleton anti-pattern. In addition, there is a general?discussion on StackOverflow, which provides excellent reasons for being careful with this design pattern.

  • Singleton patterns violate the?Single Responsibility Principle: they control their creation and lifecycle.
  • They can generally be used as a?global variable, which may lead to dependencies on the object exposed via interfaces.
  • They make it challenging to write code that is?loosely coupled.
  • Using the Singleton pattern in a?multithreaded environment is complex, and it is easy to fall into?race condition?problems during initialization.

With these pointers in mind, I hope you can confidently wield this handy and common design pattern in your day-to-day programming activities.

Happy Coding!

要查看或添加评论,请登录

社区洞察

其他会员也浏览了