Why is the Borg pattern better than the Singleton pattern in Python Why is the Borg pattern better than the Singleton pattern in Python python python

Why is the Borg pattern better than the Singleton pattern in Python


The real reason that borg is different comes down to subclassing.

If you subclass a borg, the subclass' objects have the same state as their parents classes objects, unless you explicitly override the shared state in that subclass. Each subclass of the singleton pattern has its own state and therefore will produce different objects.

Also in the singleton pattern the objects are actually the same, not just the state (even though the state is the only thing that really matters).


In python if you want a unique "object" that you can access from anywhere just create a class Unique that only contains static attributes, @staticmethods, and @classmethods; you could call it the Unique Pattern. Here I implement and compare the 3 patterns:

Unique

#Unique Patternclass Unique:#Define some static variables here    x = 1    @classmethod    def init(cls):        #Define any computation performed when assigning to a "new" object        return cls

Singleton

#Singleton Patternclass Singleton:    __single = None     def __init__(self):        if not Singleton.__single:            #Your definitions here            self.x = 1         else:            raise RuntimeError('A Singleton already exists')     @classmethod    def getInstance(cls):        if not cls.__single:            cls.__single = Singleton()        return cls.__single

Borg

#Borg Patternclass Borg:    __monostate = None    def __init__(self):        if not Borg.__monostate:            Borg.__monostate = self.__dict__            #Your definitions here            self.x = 1        else:            self.__dict__ = Borg.__monostate

Test

#SINGLETONprint "\nSINGLETON\n"A = Singleton.getInstance()B = Singleton.getInstance()print "At first B.x = {} and A.x = {}".format(B.x,A.x)A.x = 2print "After A.x = 2"print "Now both B.x = {} and A.x = {}\n".format(B.x,A.x)print  "Are A and B the same object? Answer: {}".format(id(A)==id(B))#BORGprint "\nBORG\n"A = Borg()B = Borg()print "At first B.x = {} and A.x = {}".format(B.x,A.x)A.x = 2print "After A.x = 2"print "Now both B.x = {} and A.x = {}\n".format(B.x,A.x)print  "Are A and B the same object? Answer: {}".format(id(A)==id(B))#UNIQUEprint "\nUNIQUE\n"A = Unique.init()B = Unique.init()print "At first B.x = {} and A.x = {}".format(B.x,A.x)A.x = 2print "After A.x = 2"print "Now both B.x = {} and A.x = {}\n".format(B.x,A.x)print  "Are A and B the same object? Answer: {}".format(id(A)==id(B))

Output:

SINGLETON

At first B.x = 1 and A.x = 1After A.x = 2Now both B.x = 2 and A.x = 2Are A and B the same object? Answer: TrueBORGAt first B.x = 1 and A.x = 1After A.x = 2Now both B.x = 2 and A.x = 2Are A and B the same object? Answer: FalseUNIQUEAt first B.x = 1 and A.x = 1After A.x = 2Now both B.x = 2 and A.x = 2Are A and B the same object? Answer: True

In my opinion, Unique implementation is the easiest, then Borg and finally Singleton with an ugly number of two functions needed for its definition.


It is not. What is generally not recommended is a pattern like this in python:

class Singleton(object): _instance = None def __init__(self, ...):  ... @classmethod def instance(cls):  if cls._instance is None:   cls._instance = cls(...)  return cls._instance

where you use a class method to get the instance instead of the constructor. Python's metaprogramming allows much better methods, e.g. the one on Wikipedia:

class Singleton(type):    def __init__(cls, name, bases, dict):        super(Singleton, cls).__init__(name, bases, dict)        cls.instance = None    def __call__(cls, *args, **kw):        if cls.instance is None:            cls.instance = super(Singleton, cls).__call__(*args, **kw)        return cls.instanceclass MyClass(object):    __metaclass__ = Singletonprint MyClass()print MyClass()