Singletons
- Objects that can only have a single instance, with a single point of access
- It is a global variable in an object-oriented way
- Why use it?
- Useful for maintaining a central state, where all clients need to access and operate on a common resource
- It can be used to cache information
- so as to be shared by various elements of the software system
- by keeping the information in a single object
- it is not longer required to retrieve the infromation from its original source every time
- in this case, singleton acts as a cache of the information
Structure
- The Singleton class declares the static method getInstance that returns the same instance of its own class.
- The Singleton’s constructor should be hidden from the client code.
- Calling the getInstance method should be the only way of getting the Singleton object.
Javascript
The Node.js module system provides a basic framework for implementing a rudimentary singleton
let num1 = 0;
module.exports = {
add: num => num1 + num, // module 1
subtract: num => num1 - num, // module 2
};
Creating a singleton with ES5
- When module is imported, only a single instance is created and referred to
- This is because the module system caches the module the moment it is accessed by using a require statement
- Therefore, regardless of the number of times imported, the same instance is referred and is will be accessed via the same cached and common instance
- However, although this behavior behaves like a singleton, it is technically just an instance of the module that is cached upon first access
Creating a singleton with ES6 class
- Normal way of exporting and importing Singletons defined with ES6 class with not behave like a singleton
- as they do not share the same point of access
- Need to create an instance and export the instance to make it behave like a singleton
Python
- Python modules are singletons
- but it is not a good idea to use them for the Singleton pattern
- because it is error-prone
- e.g.: if you forget the global statements, variables local to a function will be created instead
- they pollute the module namespace
- no oop benefits like associated methods or reuse through inheritance
- because it is error-prone
- but it is not a good idea to use them for the Singleton pattern
Singleton pattern
- Ensures that a class has only 1 instance
- provide a global point of access to it
- e.g. a logging class
- Pros
- Singletons are allocated once and only once
- Policies can be added to the method that provides access to the singleton pointer
- Cons
- Derivatives of Singletons are not automatically Singletons
- Singletons must always be accessed through a pointer or reference
- obtaining this has overhead
uses new method
- is the first step of instance creation
- is called before init
- is responsible for returning a new instance of the class
class Singleton:
__instance = None
def __new__(cls, val=None):
if Singleton.__instance is None:
Singleton.__instance = object.__new__(cls)
Singleton.__instance.val = val
return Singleton.__instance
Borg
- Allows a class to have as many instances as one likes
- ensures that they all share the same state
- Pros
- Derivatives of monostate classes can also be monostate
- Access to monostate objects does not have to be through pointers or references
- Cons
- No instantiation policy can exist for monostate classes
- Monostate instances may be allocated and deallocated many times
uses init method
- does not return anything
- only responsible for initializing the instance after it has been created
class Borg:
__shared_state = {} # Attribute dictionary
def __init__(self):
self.__dict__ = self._shared_state # Make it an attribute dictionary