Singleton pattern: Difference between revisions

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search
No edit summary
 
imported>TarnishedPath
m Per page move: Changed link from Class (computer programming) to Class (programming) (×2) using MovePlus
 
Line 2: Line 2:
[[File:Singleton UML class diagram.svg|thumb|A [[class diagram]] exemplifying the singleton pattern.]]
[[File:Singleton UML class diagram.svg|thumb|A [[class diagram]] exemplifying the singleton pattern.]]


In [[object-oriented programming]], the '''singleton pattern''' is a [[software design pattern]] that restricts the [[Instantiation (computer science)|instantiation]] of a [[Class (computer programming)|class]] to a singular instance. It is one of the well-known [[Design Patterns|"Gang of Four" design patterns]], which describe how to solve recurring problems in object-oriented software.<ref name="GoF">{{cite book |author=Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides |url=https://archive.org/details/designpatternsel00gamm/page/127 |title=Design Patterns: Elements of Reusable Object-Oriented Software |publisher=Addison Wesley |year=1994 |isbn=0-201-63361-2 |pages=[https://archive.org/details/designpatternsel00gamm/page/127 127ff] |url-access=registration}}</ref> The pattern is useful when exactly one object is needed to coordinate actions across a system.
In [[object-oriented programming]], the '''singleton pattern''' is a [[software design pattern]] that restricts the [[Instantiation (computer science)|instantiation]] of a [[Class (programming)|class]] to a singular instance. It is one of the well-known [[Design Patterns|"Gang of Four" design patterns]], which describe how to solve recurring problems in object-oriented software.<ref name="GoF">{{cite book |author=Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides |url=https://archive.org/details/designpatternsel00gamm/page/127 |title=Design Patterns: Elements of Reusable Object-Oriented Software |publisher=Addison Wesley |year=1994 |isbn=0-201-63361-2 |pages=[https://archive.org/details/designpatternsel00gamm/page/127 127ff] |url-access=registration}}</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>{{cite web |title=The Singleton design pattern - Problem, Solution, and Applicability |url=http://w3sdesign.com/?gr=c05&ugr=proble |access-date=2017-08-16 |website=w3sDesign.com}}</ref>
More specifically, the singleton pattern allows classes to:<ref>{{cite web |title=The Singleton design pattern - Problem, Solution, and Applicability |url=http://w3sdesign.com/?gr=c05&ugr=proble |access-date=2017-08-16 |website=w3sDesign.com}}</ref>
* Ensure they only have one instance
* Ensure they only have one instance
* Provide easy access to that instance
* Provide easy access to that instance
* Control their instantiation (for example, hiding the [[Constructor (object-oriented programming)|constructors]] of a [[Class (computer programming)|class]])
* Control their instantiation (for example, hiding the [[Constructor (object-oriented programming)|constructors]] of a [[Class (programming)|class]])


The term comes from the [[Singleton (mathematics)|mathematical concept of a singleton]].
The term comes from the [[Singleton (mathematics)|mathematical concept of a singleton]].
Line 28: Line 28:
This [[C++23]] implementation is based on the pre-C++98 implementation in the book {{Citation needed|reason=the book is ambiguous here.|date=March 2024}}.
This [[C++23]] implementation is based on the pre-C++98 implementation in the book {{Citation needed|reason=the book is ambiguous here.|date=March 2024}}.


<syntaxhighlight lang="Cpp">
<syntaxhighlight lang="cpp">
import std;
import std;


class Singleton {
class Singleton {
private:
    Singleton() = default; // no public constructor
    ~Singleton() = default; // no public destructor
    inline static Singleton* instance = nullptr; // declaration class variable
    int value;
public:
public:
  // defines an class operation that lets clients access its unique instance.
    // defines a class operation that lets clients access its unique instance.
  static Singleton& get() {
    static Singleton& getInstance() {
    // may be responsible for creating its own unique instance.
        if (!instance) {
    if (nullptr == instance) instance = new Singleton;
            instance = new Singleton();
    return *instance;
        }
  }
        return *instance;
   Singleton(const Singleton&) = delete; // rule of three
    }
  Singleton& operator=(const Singleton&) = delete;
    
  static void destruct() {
    Singleton(const Singleton&) = delete("Copy construction disabled");
    delete instance;
    Singleton& operator=(const Singleton&) = delete("Copy assignment disabled");
    instance = nullptr;
 
  }
    static void destroy() {
  // existing interface goes here
        delete instance;
  int getValue() {
        instance = nullptr;
    return value;
    }
  }
 
  void setValue(int value_) {
    // existing interface goes here
    value = value_;
    [[nodiscard]]
  }
    int getValue() const noexcept {
private:
        return value;
  Singleton() = default; // no public constructor
    }
  ~Singleton() = default; // no public destructor
 
  static Singleton* instance; // declaration class variable
    void setValue(int newValue) noexcept {
  int value;
        value = newValue;
    }
};
};
Singleton* Singleton::instance = nullptr; // definition class variable


int main() {
int main() {
  Singleton::get().setValue(42);
    Singleton::getInstance().setValue(42);
  std::println("value={}", Singleton::get().getValue());
    std::println("value = {}", Singleton::getInstance().getValue());
  Singleton::destruct();
    Singleton::destroy();
}
}
</syntaxhighlight>
</syntaxhighlight>
Line 80: Line 84:


class Singleton {
class Singleton {
private:
    Singleton() = default;
    ~Singleton() = default;
    int value;
public:
public:
  static Singleton& get() {
    static Singleton& getInstance() {
    static Singleton instance;
        static Singleton instance;
    return instance;
        return instance;
  }
    }
   int getValue() {
    
    return value;
    [[nodiscard]]
  }
    int getValue() const noexcept {
   void setValue(int value_) {
        return value;
    value = value_;
    }
  }
    
private:
    void setValue(int newValue) noexcept {
  Singleton() = default;
        value = newValue;
  ~Singleton() = default;
    }
  int value;
};
};


int main() {
int main() {
  Singleton::get().setValue(42);
    Singleton::getInstance().setValue(42);
  std::println("value={}", Singleton::get().getValue());
    std::println("value = {}", Singleton::getInstance().getValue());
}
}
</syntaxhighlight>
</syntaxhighlight>
Line 109: Line 116:
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
public class Singleton {
public class Singleton {
     private static volatile Singleton instance = null;
     private static volatile Singleton instance = null;


Line 116: Line 122:
     public static Singleton getInstance() {
     public static Singleton getInstance() {
         if (instance == null) {
         if (instance == null) {
             synchronized(Singleton.class) {
             synchronized (Singleton.class) {
                 if (instance == null) {
                 if (instance == null) {
                     instance = new Singleton();
                     instance = new Singleton();
Line 141: Line 147:


== External links ==
== External links ==
{{external links|date=November 2016}}
{{wikibooks|Computer Science/Design Patterns|Singleton|Singleton implementations in various languages}}
{{wikibooks|Computer Science/Design Patterns|Singleton|Singleton implementations in various languages}}
{{commons category}}
{{commons category}}
* Complete article "[https://howtodoinjava.com/design-patterns/creational/singleton-design-pattern-in-java/ Java Singleton Pattern Explained]"  
* Complete article "[https://howtodoinjava.com/design-patterns/creational/singleton-design-pattern-in-java/ Java Singleton Pattern Explained]"  
* Four different ways to implement singleton in Java "[https://web.archive.org/web/20150709155148/http://www.javaexperience.com/design-patterns-singleton-design-pattern/ Ways to implement singleton in Java]"  
* Four different ways to implement singleton in Java "[https://web.archive.org/web/20150709155148/http://www.javaexperience.com/design-patterns-singleton-design-pattern/ Ways to implement singleton in Java]"  
* Book extract: [https://csharpindepth.com/Articles/Singleton Implementing the Singleton Pattern in C#] by Jon Skeet
* [https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ff650849(v=pandp.10) Singleton at Microsoft patterns & practices Developer Center]
* IBM article "[https://www.ibm.com/developerworks/library/j-dcl/ Double-checked locking and the Singleton pattern]" by Peter Haggar
* {{cite web |last1=Geary |first1=David |date=2003-04-25 |df=mdy |url=https://www.infoworld.com/article/2073352/core-java-simply-singleton.html |title=How to navigate the deceptively simple Singleton pattern |department=Java Design Patterns |work=[[JavaWorld]] |access-date=2020-07-21}}
* [https://code.google.com/archive/p/google-singleton-detector/ Google Singleton Detector] (analyzes [[Java bytecode]] to detect singletons)


{{Design Patterns Patterns}}
{{Design Patterns Patterns}}

Latest revision as of 08:39, 17 October 2025

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.[1] The pattern is useful when exactly one object is needed to coordinate actions across a system.

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

  • 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 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++23 implementation is based on the pre-C++98 implementation in the book Script error: No such module "Unsubst"..

import std;

class Singleton {
private:
    Singleton() = default; // no public constructor
    ~Singleton() = default; // no public destructor
    inline static Singleton* instance = nullptr; // declaration class variable
    int value;
public:
    // defines a class operation that lets clients access its unique instance.
    static Singleton& getInstance() {
        if (!instance) {
            instance = new Singleton();
        }
        return *instance;
    }
  
    Singleton(const Singleton&) = delete("Copy construction disabled");
    Singleton& operator=(const Singleton&) = delete("Copy assignment disabled");

    static void destroy() {
        delete instance;
        instance = nullptr;
    }

    // existing interface goes here
    [[nodiscard]]
    int getValue() const noexcept {
        return value;
    }

    void setValue(int newValue) noexcept {
        value = newValue;
    }
};

int main() {
    Singleton::getInstance().setValue(42);
    std::println("value = {}", Singleton::getInstance().getValue());
    Singleton::destroy();
}

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.

import std;

class Singleton {
private:
    Singleton() = default;
    ~Singleton() = default;
    int value;
public:
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }
  
    [[nodiscard]]
    int getValue() const noexcept {
        return value;
    }
  
    void setValue(int newValue) noexcept {
        value = newValue;
    }
};

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

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.

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

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

References

Template:Reflist

External links

Template:Sister project Template:Sister project

Template:Design Patterns Patterns

  1. a b Script error: No such module "citation/CS1".
  2. Script error: No such module "citation/CS1".
  3. Script error: No such module "citation/CS1".
  4. Script error: No such module "citation/CS1".
  5. Script error: No such module "citation/CS1".
  6. Script error: No such module "citation/CS1".
  7. Script error: No such module "citation/CS1".
  8. a b c Script error: No such module "citation/CS1".
  9. Steve Yegge. Singletons considered stupid, September 2004
  10. Hevery, Miško, "Global State and Singletons", Clean Code Talks, 21 November 2008.