There are many design patterns applicable to many different situations, and each of them might have many possible implementations, specially over different technologies or programming languages (although it is a concept, or a design idea, the implementations still depends or relies on the underlying technology involved).
One popular design patter, is singleton, which is applied when we need for a class to allow just one single instance, having this way a unique possible object of that class.
This is often achieved by changing the definition of the class (hiding the constructor), declaring a variable of the type of the class which represents the instance, and then creating a new method for returning that value.
I would like to see if there is another possible way to do this (in a different technology, because the description above suggest that I was talking about Java, .NET or some similar language), but in addition to that it could be interesting to see if there is a more abstract way of do this, which means, for every time that I need a singleton-like object, I would like to use this feature without the need to rewrite the entire singleton code again.
I ran a scenario which did work on many situations, so probably this is the kind of functionality wanted.
It starts by defining a singleton object, which allows just one possible instance. This is accomplished by re-defining the __new__ method on the class, something like (a code like this one is possible to be found on the documentation or many sites related to this, it is not the main part here, instead is the analysis which follows):
class Singleton(object):
instanceObject = None
def __new__(cls,*args,**kwargs):
if not cls.instanceObject:
cls.instanceObject = super(Singleton , cls).__new__(cls,*args ,**kwargs)
return cls.instanceObject
And then I would like to use this singleton functionality for an object I might want to define, such as (the example is a bit simple, but it is just to check this feature out, it does not matter the rest of the complexity of the object):
class MyClass(Singleton):
name = None
def setName(name):
self.name = name
def getName(self):
return self.name
def __init__(self ,name):
self.name = name
Once this class is defined, it could be interesting to see if I can really get just one single instance of the class, so with something like:
a = MyClass('object named A')
b = MyClass('object named B')
print a.getName()
print b.getName()
print a == b
The result of this execution shows:
object named B
object named B
True
The last true indicate that both A and B are the same object, and this is the reason why the displayed message shows the same twice: it first creates a new object identified by the variable A and sets its name, and then B is created with a different name, but as the object was previously created, it does not create a new instance, instead uses the same object and changes it’s name (because of how was it constructed), which affects to the variable A, so this way both A and B are pointing to the same object which logically has the same name (referenced by the name property).
Here there is another similar example with a different object, but applying a similar case.
class Orchestra(Singleton):
numberOfMusicians = None
name = None
def setNumberOfMusicians(self,aNumber):
self.numberOfMusicians = aNumber
def setName(self, aName):
self.name = aName
def getNumberOfMusicians(self):
return self.numberOfMusicians
def getName(self):
return self.name
def getValues(self):
return "Name : %s - number of musicians: %s" % (self.name,
self.numberOfMusicians )
oneOrchestra = Orchestra()
anotherOrchestra = Orchestra()
anotherOrchestra.setNumberOfMusicians(0)
anotherOrchestra.setNumberOfMusicians('')
oneOrchestra.setNumberOfMusicians(30)
oneOrchestra.setName('My first orchestra')
print oneOrchestra.getValues()
print anotherOrchestra.getValues()
print oneOrchestra == anotherOrchestra
Name : My first orchestra – number of musicians: 30
Name : My first orchestra – number of musicians: 30
True
The behavior is similar.
But, how does this behaves on comparison with another regular scenario?
This question points to know what happens on an scenario without this singleton implementation.
The following code illustrates this.
class AParentClass(object):
def method(self):
return 'AParentClass'
class AChildClass(AParentClass,Singleton):
name = None
class AnotherChildClassNonSingleton(AParentClass):
name = None
def setName(self, name):
self.name = name
oneChild = AChildClass()
anotherChild = AChildClass()
oneChild.name = 'oneChild - child node'
anotherChild.name = 'another child - child node'
print oneChild.name
print anotherChild.name
print oneChild.method()
print anotherChild.method()
print oneChild == anotherChild
aNonSingletonObject = AnotherChildClassNonSingleton()
anotherNonSingletonObject = AnotherChildClassNonSingleton()
aNonSingletonObject.setName('first non singleton object')
anotherNonSingletonObject.setName('second non singleton object')
print aNonSingletonObject.name
print anotherNonSingletonObject.name
print aNonSingletonObject == anotherNonSingletonObject
And the output that produces is:
another child – child node
another child – child node
AParentClass
AParentClass
True
first non singleton object
second non singleton object
False
So here we can crearly see the difference between one scenario that handles the same object twice or many times (regardless the number of variables pointing to the same object, the important idea on this singleton implementation is that actually creates just one object and not many different), and another one which actually creates different instances (therefore different objects) on every creation process. This is the case of having a singleton implementation or not, but probably the best part is how this implementation is performed: the singleton code is just once, and this feature or behavior of the object, might be used many times by just defining the new class as a subclass of this one created.
An important note, is that this is possible due to the fact that multiple inheritance is allowed in python, otherwise this case would not be possible.
The idea was just to present a simple implementation of a curious pattern, implemented on a technology with many features and a great potential, coding with simplicity (in order not to blur the original idea).
I am aware that design patterns are an special topic, and that it is often said that python abstracts or includes many of this on its internal implementation without need to follow “external” considerations, but I will probably write about that in a further post, so far the challenge was to present an implementation like this one of the singleton pattern in order to see if it could be possible to have it “generically”.
So far it seemed it is, regardless all the possible implementations (it might be a very particular scenario when some code like this one has problems, but despite that it is a feasible codification). It is not a minor detail the role that the technology plays here: having coded this on a high level language like python is probably one of the key points in order to make this possible, and keeping the code simple and object oriented is a good thing.
References
- Design-patterns – Erich Gamma, Addison Wesley
- Python – Multiple inheritance
- Singleton pattern
- Python reference model
- stack overflow
Stories on Linux