Intent
Ensure a class only has one instance, and provide a global point of access to it.
Motivation
- Some classes only need one instance.
- This allows better control over the one instance.
- Ensures that it’s not possible, for example, that a client may log in twice, but rather logs in once and provides a global point of access for that instance.
Applicability
Use the Singleton pattern when:
- There must be exactly one instance of a class
- When the sole instance should be extensible by subclassing or extended instance without modifying original code.
Structure

Participants
- Singleton
- Defines an instance operation that lets clients access its one and only instance.
- May be responsible for creating its own unique instance.
Implementation
Info
The following code is written in Dart.
Why use one when you have global objects? global object. However, if it is done with a global object, it can be messy and an unique instance is never guaranteed - hence, the benefits of using a Singleton.
A lot of newer modern languages (as in Python and JS, like always) lack the need for a standard Singleton. Although it is possible, they can be just created as a
Standard implementation
- The
Singletonshould only be instantiated by a private constructor - it can only be instantiated inside itself, nowhere else.- This can be done by:
- Writing the constructor method inside a private access specifier so that it can only be constructed when called inside itself (private).
- Returning the instance when the class is called outside itself so that it returns its only instance when called outside itself (public).
class Singleton{
// Private constructor so that this instance can only be instantiated
// from inside the class.
Singleton._privateConstructor()
// creates the only instance under the variable _instance
static final Singleton _instance = Singleton._privateConstructor()
// public constructor, it will return the the only instance.
factory Singleton(){
return _instance
}
}
void main(){
var singleton1 = Singleton();
var singleton2 = Singleton();
print(singleton1 == singleton2); // will be true, as it is the same instance.
}Subclassing
Singletons get a bit more complicated when you want to subclass one. There aren’t many reasons why you would want to subclass Singleton, but there are solutions.
- It is much harder to return a specific version of the singleton - as there is obviously only one instance of it (so technically only ‘one version’).
Solution 1:
Setup cases in the single instance, with a separate singleton for each case.
This doesn’t work dynamically. If you want to add more subclasses, you’d have to manually add the subclasses to the switch case (and possibly an enum too).
enum subclasses = {subclass1, subclass2} // needs a enum of all potential subclasses
class Singleton{
Singleton._privateConstructor()
static final Singleton _instance = Singleton._privateConstructor()
// Public factory that returns the requested subclass, or itself by default.
factory Singleton(subclasses subclass){
switch(subclass){
case subclasses.subclass1:
return SingletonSubclass1._instance
case subclasses.subclass2:
return SingletonSubclass2._instance
default:
return _instance_
}
}
}
// Subclasses
class SingletonSubclass1 extends Singleton{
SingletonSubclass1._privateConstructor(): super._privateConstructor();
static final SingletonSubclass1 _instance = SingletonSubcllass1._privateConstructor()
}
class SingletonSubclass2 extends Singleton{
SingletonSubclass2._privateConstructor(): super._privateConstructor();
static final SingletonSubclass2 _instance = SingletonSubcllass2._privateConstructor()
}Solution 2:
Instead of a Singleton, the parent Singleton classes are instead registries of singleton subclasses. This allows a subclass to be dynamically “registered” into the parent Singleton class - so therefore allowing subclasses to be created dynamically.
class Singleton{
// a hashmap containing all subclasses.
static final Map<String, Singleton> _registry = {};
Singleton._privateConstructor();
static final Singleton _instance = Singleton._privateConstructor()
// Calling this function with a name will return the instance of the subclass.
factory Singleton(String name){
_instance = lookup(name)
return _instance
}
//Adds a new singleton subclass to the registry under the name defined by name.
void register(String name, Singleton singleton){
_registry.update(name, (value)=> singleton, ifAbsent: () => singleton)
}
// lookup function to find subclass.
singleton lookup(String name){
if(!_registry.containsKey(name)){
throw Exception('Subclass not found')
}
return _registry[name]
}
}Consequences
- Controlled access to the sole instance.
- Reduced name space - avoids polluting the global namespace like global objects would.
- Easy to configure - easily modifiable, to extend and to reconfigure at run-time.
- Static and single-instanced variables make it easier for you to keep track of how the class may be used and modified.
Related patterns
- Abstract Factory
- Builders
- Prototypes