Singleton pattern ensures that class has only one instance.
aka Anti-Pattern - as it can interfere with unit testing
- A design pattern that restricts the instantiation of a class to one object
- Ensures that only one instance is created and only when the instance is needed.
Common Uses of Singleton Pattern:
- Logger Classes: The Singleton pattern is used in the design of logger classes. To provide a global logging access point in all the application components without being necessary to create an object each time a logging operation is performed.
- Configuration Classes: The Singleton pattern is used to design the classes which provide the configuration settings for an application. By implementing configuration classes as Singleton not only that we provide a global access point, but we also keep the instance we use as a cache object. When the class is instantiated (or when a value is read) the singleton will keep the values in its internal structure. If the values are read from the database or from files this avoids the reloading the values each time the configuration parameters are used.
- Accessing resources in shared mode: It can be used in the design of an application that needs to work with the serial port. Let's say that there are many classes in the application, working in a multi-threading environment, which needs to operate actions on the serial port. In this case, a singleton with synchronized methods could be used to manage all the operations on the serial port.
- Factories implemented as Singletons
- Let's assume that we design an application with a factory to generate new objects (Account, Customer, Site, Address objects) with their IDs, in a multithreading environment. If the factory is instantiated twice in 2 different threads then it is possible to have 2 overlapping IDs for 2 different objects. If we implement the Factory as a singleton we avoid this problem. Combining Abstract Factory or Factory Method and Singleton design patterns is a common practice.
- The Abstract Factory, Builder, and Prototype patterns can use Singletons in their implementation.
- Facade Objects are often Singletons because only one Facade object is required.
- State objects are often Singletons.
- Singletons are often preferred to global variables because:
- They do not pollute the global namespace (or, in languages with namespaces, their containing namespace) with unnecessary variables.
- They permit lazy allocation and initialization, whereas global variables in many languages will always consume resources.
Singleton provides a global, single instance by:
- Making the class create a single instance of itself.
- Allowing other objects to access this instance through a class method that returns a reference to the instance. A class method is globally accessible.
- Declaring the class constructor as private so that no other object can create a new instance.
Advantages of Singleton Pattern:
- The static initialization approach is possible because of the .NET Framework explicitly defines how and when static variable initialization occurs.
- The Double-Check Locking idiom described below in "Multithreaded Singleton" is implemented correctly in the common language runtime.
Disadvantages or liabilities of Singleton Pattern:
- Unit testing far more difficult as it introduces global state into an application.
- Reduces the potential for parallelism within a program, because access to the singleton in a multi-threaded context must be serialized, e.g., by locking.
- Requires explicit initialization in a multithreaded application, and we have to take precautions to avoid threading issues.
- Advocates of dependency injection would regard this as an anti-pattern, mainly due to its use of private and static methods.
- The singleton instance is obtained using the class name. At the first view, this is an easy way to access it, but it is not very flexible. If we need to replace the Singleton class, all the references in the code should be changed accordingly.
- Some have suggested ways break down the singleton pattern using methods such as reflection in languages such as C#, Java etc.