Singleton pattern

Last updated
A class diagram exemplifying the singleton pattern. Singleton UML class diagram.svg
A class diagram exemplifying the singleton pattern.

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 describes 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.

Contents

More specifically, the singleton pattern allows objects to: [2]

The term comes from the mathematical concept of a singleton.

Common uses

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. [1] [3]

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. [4]

Implementations

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++11 implementation is based on the pre C++98 implementation in the book [ citation needed ].

#include<iostream>classSingleton{public:// defines an class operation that lets clients access its unique instance.staticSingleton&get(){// may be responsible for creating its own unique instance.if(nullptr==instance)instance=newSingleton;return*instance;}Singleton(constSingleton&)=delete;// rule of threeSingleton&operator=(constSingleton&)=delete;staticvoiddestruct(){deleteinstance;instance=nullptr;}// existing interface goes hereintgetValue(){returnvalue;}voidsetValue(intvalue_){value=value_;}private:Singleton()=default;// no public constructor~Singleton()=default;// no public destructorstaticSingleton*instance;// declaration class variableintvalue;};Singleton*Singleton::instance=nullptr;// definition class variableintmain(){Singleton::get().setValue(42);std::cout<<"value="<<Singleton::get().getValue()<<'\n';Singleton::destruct();}

The program output is

value=42

This is an implementation of the Meyers singleton [5] in C++11. The Meyers singleton has no destruct method. The program output is the same as above.

#include<iostream>classSingleton{public:staticSingleton&get(){staticSingletoninstance;returninstance;}intgetValue(){returnvalue;}voidsetValue(intvalue_){value=value_;}private:Singleton()=default;~Singleton()=default;intvalue;};intmain(){Singleton::get().setValue(42);std::cout<<"value="<<Singleton::get().getValue()<<'\n';}

Lazy initialization

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 [6] is a thread-safe implementation, using lazy initialization with double-checked locking.

publicclassSingleton{privatestaticvolatileSingletoninstance=null;privateSingleton(){}publicstaticSingletongetInstance(){if(instance==null){synchronized(Singleton.class){if(instance==null){instance=newSingleton();}}}returninstance;}}

Criticism

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. [7] This increased coupling can introduce difficulties with unit testing. [8] In turn, this places restrictions on any abstraction that uses the singleton, such as preventing concurrent use of multiple instances. [8] [9] [10]

Singletons also violate the single-responsibility principle because they are responsible for enforcing their own uniqueness along with performing their normal functions. [8]

See also

Related Research Articles

<span class="mw-page-title-main">Abstract factory pattern</span> Software design pattern

The abstract factory pattern in software engineering is a design pattern that provides a way to create families of related objects without imposing their concrete classes, by encapsulating a group of individual factories that have a common theme without specifying their concrete classes. According to this pattern, a client software component creates a concrete implementation of the abstract factory and then uses the generic interface of the factory to create the concrete objects that are part of the family. The client does not know which concrete objects it receives from each of these internal factories, as it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from their general usage and relies on object composition, as object creation is implemented in methods exposed in the factory interface.

In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. It is a kind of lazy evaluation that refers specifically to the instantiation of objects or other resources.

The prototype pattern is a creational design pattern in software development. It is used when the types of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used to avoid subclasses of an object creator in the client application, like the factory method pattern does, and to avoid the inherent cost of creating a new object in the standard way when it is prohibitively expensive for a given application.

In software engineering, double-checked locking is a software design pattern used to reduce the overhead of acquiring a lock by testing the locking criterion before acquiring the lock. Locking occurs only if the locking criterion check indicates that locking is required.

A method in object-oriented programming (OOP) is a procedure associated with an object, and generally also a message. An object consists of state data and behavior; these compose an interface, which specifies how the object may be used. A method is a behavior of an object parametrized by a user.

In computer programming, specifically object-oriented programming, a class invariant is an invariant used for constraining objects of a class. Methods of the class should preserve the invariant. The class invariant constrains the state stored in the object.

In computer programming, run-time type information or run-time type identification (RTTI) is a feature of some programming languages that exposes information about an object's data type at runtime. Run-time type information may be available for all types or only to types that explicitly have it. Run-time type information is a specialization of a more general concept called type introspection.

This article compares two programming languages: C# with Java. While the focus of this article is mainly the languages and their features, such a comparison will necessarily also consider some features of platforms and libraries. For a more detailed comparison of the platforms, see Comparison of the Java and .NET platforms.

In class-based, object-oriented programming, a constructor is a special type of function called to create an object. It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.

<span class="mw-page-title-main">Java syntax</span> Set of rules defining correctly structured program

The syntax of Java is the set of rules defining how a Java program is written and interpreted.

In computer programming, thread-local storage (TLS) is a memory management method that uses static or global memory local to a thread. The concept allows storage of data that appears to be global in a system with separate threads.

<span class="mw-page-title-main">Multiton pattern</span> Software engineering design pattern

In software engineering, the multiton pattern is a design pattern which generalizes the singleton pattern. Whereas the singleton allows only one instance of a class to be created, the multiton pattern allows for the controlled creation of multiple instances, which it manages through the use of a map.

In the C++ programming language, new and delete are a pair of language constructs that perform dynamic memory allocation, object construction and object destruction.

A class in C++ is a user-defined type or data structure declared with any of the keywords class, struct or union that has data and functions as its members whose access is governed by the three access specifiers private, protected or public. By default access to members of a C++ class declared with the keyword class is private. The private members are not accessible outside the class; they can be accessed only through member functions of the class. The public members form an interface to the class and are accessible outside the class.

C++11 is a version of the ISO/IEC 14882 standard for the C++ programming language. C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14. The name follows the tradition of naming language versions by the publication year of the specification, though it was formerly named C++0x because it was expected to be published before 2010.

In software engineering, the initialization-on-demand holder idiom is a lazy-loaded singleton. In all versions of Java, the idiom enables a safe, highly concurrent lazy initialization of static fields with good performance.

In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (null) behavior. The null object design pattern, which describes the uses of such objects and their behavior, was first published as "Void Value" and later in the Pattern Languages of Program Design book series as "Null Object".

This article describes the syntax of the C# programming language. The features described are compatible with .NET Framework and Mono.

In software engineering, the module pattern is a design pattern used to implement the concept of software modules, defined by modular programming, in a programming language with incomplete direct support for the concept.

References

  1. 1 2 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software . Addison Wesley. pp.  127ff. ISBN   0-201-63361-2.{{cite book}}: CS1 maint: multiple names: authors list (link)
  2. "The Singleton design pattern - Problem, Solution, and Applicability". w3sDesign.com. Retrieved 2017-08-16.
  3. Soni, Devin (31 July 2019). "What Is a Singleton?". BetterProgramming. Retrieved 28 August 2021.
  4. Rainsberger, J.B. (1 July 2001). "Use your singletons wisely". IBM. Archived from the original on 24 February 2021. Retrieved 28 August 2021.
  5. Scott Meyers (1997). More Effective C++. Addison Wesley. pp. 146 ff. ISBN   0-201-63371-X.
  6. Eric Freeman, Elisabeth Freeman, Kathy Sierra, and Bert Bates (October 2004). "5: One of a Kind Objects: The Singleton Pattern". Head First Design Patterns (First ed.). O'Reilly Media, Inc. p. 182. ISBN   978-0-596-00712-6.{{cite book}}: CS1 maint: multiple names: authors list (link)
  7. "Why Singletons Are Controversial". Google Code Archive. Archived from the original on 6 May 2021. Retrieved 28 August 2021.
  8. 1 2 3 Button, Brian (25 May 2004). "Why Singletons are Evil". Being Scott Densmore. Microsoft. Archived from the original on 15 July 2021. Retrieved 28 August 2021.
  9. Steve Yegge. Singletons considered stupid, September 2004
  10. Hevery, Miško, "Global State and Singletons", Clean Code Talks, 21 November 2008.