75 votes

Pourquoi le modèle Borg est-il meilleur que le modèle Singleton en Python ?

Pourquoi le Modèle Borg mieux que le Modèle singleton ?

Je pose la question parce que je ne vois pas comment ils pourraient aboutir à quelque chose de différent.

Borg :

class Borg:
  __shared_state = {}
  # init internal state variables here
  __register = {}
  def __init__(self):
    self.__dict__ = self.__shared_state
    if not self.__register:
      self._init_default_register()

Singleton :

class Singleton:
  def __init__(self):
    # init internal state variables here
    self.__register = {}
    self._init_default_register()

# singleton mechanics external to class, for example this in the module
Singleton = Singleton()

Ce que je veux montrer ici, c'est que l'objet service, qu'il soit implémenté en tant que Borg ou Singleton, a un état interne non trivial (il fournit un service basé sur celui-ci) (je veux dire que cela doit être quelque chose d'utile, ce n'est pas un Singleton/Borg juste pour le fun).

Et cet état doit être initié. Ici, l'implémentation de Singleton est plus simple, puisque nous traitons init comme la mise en place de l'état global. Je trouve gênant que l'objet Borg doive interroger son état interne pour savoir s'il doit se mettre à jour.

Plus l'état interne est important, plus la situation s'aggrave. Par exemple, si l'objet doit écouter le signal de démontage de l'application pour enregistrer son registre sur le disque, cet enregistrement ne doit être effectué qu'une seule fois, ce qui est plus facile avec un Singleton.

58voto

David Raznick Points 5074

La véritable raison pour laquelle Borg est différent est la sous-classification.

Si vous sous-classez un borg, les objets de la sous-classe ont le même état que les objets de la classe mère, à moins que vous ne remplaciez explicitement l'état partagé dans cette sous-classe. Chaque sous-classe du modèle singleton a son propre état et produira donc des objets différents.

De plus, dans le modèle singleton, les objets sont en fait les mêmes, pas seulement l'état (même si l'état est la seule chose qui compte vraiment).

22voto

Cristian Garcia Points 805

En python, si vous voulez un "objet" unique auquel vous pouvez accéder de n'importe où, créez simplement une classe. Unique qui ne contient que des attributs statiques, @staticmethod et @classmethod on pourrait l'appeler le modèle unique. Ici, je mets en œuvre et compare les 3 modèles :

Unique en son genre

#Unique Pattern
class 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 Pattern
class 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 Pattern
class 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

#SINGLETON
print "\nSINGLETON\n"
A = Singleton.getInstance()
B = Singleton.getInstance()

print "At first B.x = {} and A.x = {}".format(B.x,A.x)
A.x = 2
print "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))

#BORG
print "\nBORG\n"
A = Borg()
B = Borg()

print "At first B.x = {} and A.x = {}".format(B.x,A.x)
A.x = 2
print "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))

#UNIQUE
print "\nUNIQUE\n"
A = Unique.init()
B = Unique.init()

print "At first B.x = {} and A.x = {}".format(B.x,A.x)
A.x = 2
print "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))

Sortie :

SINGLETON

At first B.x = 1 and A.x = 1
After A.x = 2
Now both B.x = 2 and A.x = 2

Are A and B the same object? Answer: True

BORG

At first B.x = 1 and A.x = 1
After A.x = 2
Now both B.x = 2 and A.x = 2

Are A and B the same object? Answer: False

UNIQUE

At first B.x = 1 and A.x = 1
After A.x = 2
Now both B.x = 2 and A.x = 2

Are A and B the same object? Answer: True

À mon avis, l'implémentation Unique est la plus facile, puis Borg et enfin Singleton avec un nombre affreux de deux fonctions nécessaires à sa définition.

13voto

bayer Points 4202

Ce n'est pas le cas. Ce qui n'est généralement pas recommandé, c'est un modèle comme celui-ci en python :

class Singleton(object):

 _instance = None

 def __init__(self, ...):
  ...

 @classmethod
 def instance(cls):
  if cls._instance is None:
   cls._instance = cls(...)
  return cls._instance

où vous utilisez une méthode de classe pour obtenir l'instance au lieu du constructeur. La métaprogrammation de Python permet des méthodes bien meilleures, par exemple celle de wikipedia : http://en.wikipedia.org/wiki/Singleton_pattern#Python .

8voto

Zed Points 27408

Une classe décrit essentiellement comment vous pouvez accéder (lire/écrire) à l'état interne de votre objet.

Dans le modèle singleton, vous ne pouvez avoir qu'une seule classe, c'est-à-dire que tous vos objets vous donneront les mêmes points d'accès à l'état partagé. Cela signifie que si vous devez fournir une API étendue, vous devrez écrire un wrapper, enveloppant le singleton.

Dans le modèle borg, vous êtes en mesure d'étendre la classe de base "borg", et ainsi d'étendre plus facilement l'API à votre goût.

8voto

Lennart Regebro Points 52510

Il n'est meilleur que dans les rares cas où il y a vraiment une différence. Comme lorsque vous sous-classez. Le modèle Borg est extrêmement inhabituel, je n'en ai jamais eu besoin pour de vrai en dix ans de programmation Python.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X