Singleton is one of the classical and the most known and popular design patterns. There are many discussions about if singleton should be qualified as an anti pattern or more as a correct solution — but in this post I want to talk about another design pattern, which could be treated as more complex version of singleton.
Quoting Wikipedia for singleton Singleton:
In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object
Let’s introduce a small implementation of the very simple Singleton.
This implementation of singleton is very simple and the main point is using inner class. The instance of this inner class is what we get in return, when a developer creates a new instance of our Singleton class. So, the inner class __Singleton is kind of container for a data.
Now, look at this code:
Please note that objA and objB are the same instances. Their id is identical.
Now, let’s look at the second one — Borg (which is also known as Monostate). Monostate solves the same problem as Singleton, but in different way.
Let’s start with example of implementation:
The code is also not complicated. The main difference between Monostate and Signleton is how they keep data. Creating new instance of Borg does not return the exact object, but new allocated structure. For keeping data (to be correct — we should use ‘state’ word) the borg uses __shared_state which is assigned to __dict field. (this field is used in python class as a place to collect all fields of object together)
We can say that the main difference is the fact that creating singleton will return always the same instance when creating borg will return new object (but this objects share all fields). So, why we should use monostate and what is the advantage over the singleton? In normal case we want to use singleton because we need to have some shared data between all instances of our class. But we don’t care if this instance is exactly the same, we care only about the data.
If we are able to sacrifice identity of instance (which can be a problem if our program uses `is as a operator for comparison) then we can use borg idiom, which gives us one big feature — subclassing.
For the monostate the subclassing is working in normal way. We are able to create a child-object, and what is more important thing (and also more interest for us) child object is sharing data with his parent class. This feature of Borg idiom is a big change, because we can organize our code which is related to borg’s data in class. Every method which was used for parsing singleton’s data, could be wrapped into a class. Also we can use normal techniques which are used in OOP like overloading of methods.
In conclusion, I believe that because subclassing works in normal way for borg idiom, we are able to encapsulate methods in class. Thanks to encapsulating we are able to create cleaner code what is always a good thing.