Template:Short description

File:Singleton UML class diagram.svg
A class diagram exemplifying the singleton pattern.

In object-oriented programming, the singleton pattern is a software design pattern that restricts the instantiation of a class to a singular instance. It is one of the well-known "Gang of Four" design patterns, which describe how to solve recurring problems in object-oriented software.<ref name="GoF">Template:Cite book</ref> The pattern is useful when exactly one object is needed to coordinate actions across a system.

More specifically, the singleton pattern allows classes to:<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

  • Ensure they only have one instance
  • Provide easy access to that instance
  • Control their instantiation (for example, hiding the constructors of a class)

The term comes from the mathematical concept of a singleton.

Common usesEdit

Singletons are often preferred to global variables because they do not pollute the global namespace (or their containing namespace). Additionally, they permit lazy allocation and initialization, whereas global variables in many languages will always consume resources.<ref name="GoF" /><ref name="devin">Template:Cite news</ref>

The singleton pattern can also be used as a basis for other design patterns, such as the abstract factory, factory method, builder and prototype patterns. Facade objects are also often singletons because only one facade object is required.

Logging is a common real-world use case for singletons, because all objects that wish to log messages require a uniform point of access and conceptually write to a single source.<ref name="rainsberger">Template:Cite news</ref>

ImplementationsEdit

Implementations of the singleton pattern ensure that only one instance of the singleton class ever exists and typically provide global access to that instance.

Typically, this is accomplished by:

The instance is usually stored as a private static variable; the instance is created when the variable is initialized, at some point before when the static method is first called.

This C++23 implementation is based on the pre-C++98 implementation in the book Template:Citation needed.

<syntaxhighlight lang="Cpp"> import std;

class Singleton { public:

 // defines an class operation that lets clients access its unique instance.
 static Singleton& get() {
   // may be responsible for creating its own unique instance.
   if (nullptr == instance) instance = new Singleton;
   return *instance;
 }
 Singleton(const Singleton&) = delete; // rule of three
 Singleton& operator=(const Singleton&) = delete;
 static void destruct() {
   delete instance;
   instance = nullptr;
 }
 // existing interface goes here
 int getValue() {
   return value;
 }
 void setValue(int value_) {
   value = value_;
 }

private:

 Singleton() = default; // no public constructor
 ~Singleton() = default; // no public destructor
 static Singleton* instance; // declaration class variable
 int value;

};

Singleton* Singleton::instance = nullptr; // definition class variable

int main() {

 Singleton::get().setValue(42);
 std::println("value={}", Singleton::get().getValue());
 Singleton::destruct();

} </syntaxhighlight>

The program output is

<syntaxhighlight lang="c++"> value=42 </syntaxhighlight>

This is an implementation of the Meyers singleton<ref>Template:Cite book</ref> in C++11. The Meyers singleton has no destruct method. The program output is the same as above.

<syntaxhighlight lang="Cpp"> import std;

class Singleton { public:

 static Singleton& get() {
   static Singleton instance;
   return instance;
 }
 int getValue() {
   return value;
 }
 void setValue(int value_) {
   value = value_;
 }

private:

 Singleton() = default;
 ~Singleton() = default;
 int value;

};

int main() {

 Singleton::get().setValue(42);
 std::println("value={}", Singleton::get().getValue());

} </syntaxhighlight>

Lazy initializationEdit

A singleton implementation may use lazy initialization in which the instance is created when the static method is first invoked. In multithreaded programs, this can cause race conditions that result in the creation of multiple instances. The following Java 5+ example<ref>Template:Cite book</ref> is a thread-safe implementation, using lazy initialization with double-checked locking.

<syntaxhighlight lang="java"> public class Singleton {

   private static volatile Singleton instance = null;
   private Singleton() {}
   public static Singleton getInstance() {
       if (instance == null) {
           synchronized(Singleton.class) {
               if (instance == null) {
                   instance = new Singleton();
               }
           }
       }
       return instance;
   }

} </syntaxhighlight>

CriticismEdit

Some consider the singleton to be an anti-pattern that introduces global state into an application, often unnecessarily. This introduces a potential dependency on the singleton by other objects, requiring analysis of implementation details to determine whether a dependency actually exists.<ref name="google">{{#invoke:citation/CS1|citation |CitationClass=web }}</ref> This increased coupling can introduce difficulties with unit testing.<ref name="button">Template:Cite news</ref> In turn, this places restrictions on any abstraction that uses the singleton, such as preventing concurrent use of multiple instances.<ref name="button" /><ref>Steve Yegge. Singletons considered stupid, September 2004</ref><ref name="googletesting.blogspot.com">Hevery, Miško, "Global State and Singletons", Clean Code Talks, 21 November 2008.</ref>

Singletons also violate the single-responsibility principle because they are responsible for enforcing their own uniqueness along with performing their normal functions.<ref name="button" />

See alsoEdit

ReferencesEdit

Template:Reflist

External linksEdit

Template:External links Template:Sister project Template:Sister project

|CitationClass=web }}

Template:Design Patterns Patterns