Singleton (design pattern)

from Wikipedia, the free encyclopedia

The Singleton (rarely single piece is called) into the software development employed design patterns and belongs to the category of the generation pattern (Engl. Creational patterns ). It ensures that there is exactly one object of a class. This singleton is also usually available globally. The pattern is one of the patterns published by the so-called Gang of Four (GoF).

use

The singleton is used when

  • only one object may exist for a class and simple access to this object is required or
  • the only object is to be specialized by subclassing.

Application examples are

  • a central log object that writes output to a file .
  • Print jobs that are sent to a printer should only be written to a single buffer .

UML diagram

Singleton UML class diagram.svg

properties

The single piece (singleton)

  • creates and manages the only object in the class
  • provides global access to this object via an instance operation ( getInstance () ).

It is

  • the instance operation is a class method, that is, statically bound
  • the private attribute “instance” ( singleton ) is a class attribute, that is, a static attribute.

The names from the figure above are in brackets.

advantages

The pattern offers an improvement over global variables:

  • Access control can be implemented.
  • The singleton can be specialized by subclassing.
  • Which subclass should be used can be decided at runtime.
  • The single instance only needs to be created when it is needed.
  • If several objects are required later, a change is easier than with global variables.

disadvantage

  • There is a great danger of implementing an equivalent to global variables through excessive use of singletons and then programming procedurally instead of object-oriented.
  • Singleton class dependencies are obfuscated; H. Whether a singleton class is used cannot be determined from the interface of a class, but only from the implementation. In addition, the coupling is increased, which limits reusability and clarity.
  • The “scope” of a singleton, i.e. the area in which a singleton is actually technically “individual”, does not have to coincide with the area in which it should be “individual”. Specifically, with concurrent or even distributed systems, it is difficult to ensure that only one instance really exists.
    • For example, in Java there is a simple static variable “individually per ClassLoader”; In distributed (for example cluster-capable) systems or complex concurrent applications such as application servers , several instances can thus again exist side by side.
    • In systems with parallel processes ( threads ), it must be ensured that parallel initialization does not result in more than one instance briefly existing; and that the singleton object can later be used in many parallel processes, i.e. it is thread-safe .
    • If dynamic libraries are used, it may be necessary to It may be ensured that only one instance can exist here as well.
    • If the singleton is a generic type , the compiler dynamically creates a separate class for each combination of type parameters used. This may be correct and intentional, but it can also have unexpected side effects, e.g. B. that the constructor and all further initializations of Singleton <T> can be run through multiple times, which often contradicts the logic of an ordinary Singleton.
  • Testing a singleton can be complicated. The mocking of a singleton object is complex and in some cases - for example, if should be created for testing purposes errors - almost impossible. However, with the Java Reflection API it is possible to violate the encapsulation of the singleton and to control the instantiation.
  • The configuration of the singleton is - at least with lazy initialization (see below) - only possible via other singletons, for example environment variables, from a registry, from “well-known” files or similar.
  • Resource deallocation of resources using the singleton is difficult. For example, with a singleton for a logging system, it is often unclear when the log file should be closed.

Because of its many disadvantages, the singleton pattern (and also the idiom double-checked locking ) is sometimes rated as an anti-pattern . For cases in which there is actually a technically suitable area for a singleton, singletons can be useful - especially if they refer to other "unique structures" such as an abstract factory . Still, the correct design of singletons is difficult - usually more difficult than designs without singletons.

Use in analysis

In the analysis, a (technical) singleton is usually characterized by the fact that the multiplicity of the class is defined as 1. As in design, the area of ​​multiplicity must be questioned: Is there really only "one central point for ...", or can, for example, several objects of the same kind exist in cross-border systems?

implementation

From Lazy Creation is when the only object of the class is generated until it is needed. The aim is that the memory requirement and the computing time for instantiating the object are only used when the object is really needed. To do this, the constructor is only called the first time the function is getInstance()called.

With suitable means, Lazy Creation Singleton implementations can be made safe with regard to concurrency by marking the central method getInstancewith the keyword in Java, for example synchronized. A simpler alternative to this, however, is the option of generating the singleton during the initialization of the class; the access method then only has to return it. Therefore it does not have to be synchronized, which speeds up access a bit. This process is also known as eager creation (German "greedy generation").

If a singleton doesn't have to be derived from another class, you can simply declare the class as static - that still corresponds to the singleton principle. These so-called monostate classes (also called Borg patterns ) were proposed by S. Ball and J. Crawford in their article " Monostate classes: the power of one ". Any number of instances of a class can exist here, but they share a common state. In C ++, Java and PHP this can easily be done by declaring all class attributes as static . The name Borg comes from a posting by Alex Martelli on ASPN and refers to Star Trek .

In programming languages ​​that support enums (such as Java version 5 or higher ), the language construct enumcan be used to implement the singleton pattern , which also enables direct serialization. This also makes it impossible to derive the singleton from another class.

If you want a certain number of instances of a class ( multitone ), you can simply add further static public instance fields ( public static readonly Singleton Instance2 = new Singleton();).

An alternative, which the instance does not getInstance()generate until the first time is called, is known as the initialization on demand holder idiom . The instance is created in an inner class Holder, which is only getInstance()loaded when you first call , and not when the class is loaded Singleton.

For code examples, see List of Singleton Implementations .

Related design patterns

The properties of the singleton apply to many classes of the other patterns, so that these are then executed as a singleton.

For example, abstract factories , builders, or prototypes are often singletons as well.

Web links

Wikibooks: Pattern: Singleton  - Learning and teaching materials

Individual evidence

  1. Erich Gamma , Richard Helm , Ralph Johnson , John Vlissides : Design pattern . 5th edition. Addison-Wesley , 1996, ISBN 3-8273-1862-9 , pp. 157 .
  2. ^ Singleton Considered Stupid
  3. ^ Singletons are Pathological Liars
  4. ^ S. Ball, J. Crawford: Monostate classes , ACM Digital Library
  5. ^ Robert C. Martin: More C ++ Gems, p. 223
  6. Alex Martelli: Singleton? We don't need no stinkin 'singleton: the Borg design pattern. Posting in the "ActiveState Programmer Network" on August 27, 2001 [22. January 2006]
  7. Joshua Bloch: Effective Java Second Edition. Item 3: Enforce the singleton property with a private constructor or an enum type