There are about 26 Patterns currently discovered (I hardly think I will do them all…). Singleton is one of them. This is a very popular design pattern. In this slide, I will discuss the Singleton design pattern in the easiest way.
2. What is it ?
The Singleton Design Pattern is a Creational pattern, whose objective is to create only one
instance of a class and to provide only one global access point to that object.
Using a singleton pattern has many benefits. A few of them are:
● To limit concurrent access to a shared resource.
● To create a global point of access for a resource.
● To create just one instance of a class, throughout the lifetime of a program.
3. A singleton is used in the printer management software to process queries without modification and ultimately print.
credit: www.ionos.com
4. A class using the singleton design pattern will include,
1. A private static variable, holding the only instance of the class.
2. A private constructor, so it cannot be instantiated anywhere else.
3. A public static method, to return the single instance of the class.
5. Different ways to implement a Singleton:
A singleton pattern can be implemented in three different ways. They are as follows:
● Module-level Singleton
● Classic Singleton
● Borg Singleton
6. Module-level Singleton:
All modules are singleton, by definition. Let’s create a simple module-level singleton where
the data is shared among other modules.Here we will create three python files –
singleton.py, module1.py, and module2.py – in which the other sample modules share a
variable from singleton.py.
## singleton.py file
shared_variable = "Shared Variable"
## module1.py file
import singleton
print(singleton.shared_variable)
singleton.shared_variable += "(modified by samplemodule1)"
8. Classic Singleton:
Classic Singleton creates an instance only if there is no instance created so far; otherwise, it
will return the instance that is already created.
9. Let’s take a look at the below code.
class Singleton(object):
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
output:
10. Try to subclass the Singleton class with another one.
class Child(Singleton):
pass
If it’s a successor of Singleton, all of its instances should also be the instances of Singleton,
thus sharing its states. But this doesn’t work as illustrated in the following code:
To avoid this situation, the borg singleton is used.
11. Borg Singleton:
Borg is also known as monostate. In the borg pattern, all of the instances are different, but
they share the same state. In the following code , the shared state is maintained in the
_shared_state attribute. And all new instances of the Borg class will have this state as
defined in the __new__ class method.
12. class Borg(object):
_shared_state = {}
def __new__(cls, *args, **kwargs):
obj = super(Borg, cls).__new__(cls, *args, **kwargs)
obj.__dict__ = cls._shared_state
return obj
>>> from example1 import Borg
>>> class Child(Borg):
... pass
...
>>> borg = Borg()
>>> new_borg = Borg()
>>> print(borg is new_borg)
False
>>> child = Child()
>>> borg.only_one_var = "I'm the only one var"
>>> child.only_one_var
"I'm the only one var"
Here is how it works with subclassing:
13. You can use a metaclass if you want to use instance as a property. For example;
class Singleton(type):
# Inherit from "type" in order to gain access to method __call__
def __init__(self, *args, **kwargs):
self.__instance = None # Create a variable to store the object reference
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if self.__instance is None:
# if the object has not already been created
self.__instance = super().__call__(*args, **kwargs) # Call the __init__ method of the subclass (Spam) and save the
reference
return self.__instance
else:
# if object (Spam) reference already exists; return it
return self.__instance
class Spam(metaclass=Singleton):
def __init__(self, x):
print('Creating Spam')
self.x = x
if __name__ == '__main__':
spam = Spam(100)
spam2 = Spam(200)
14. Which type of singleton should be used is up to you?
If you expect that your singleton will not be inherited, you can choose the classic singleton;
otherwise, it’s better to stick with borg.