代码之家  ›  专栏  ›  技术社区  ›  u0b34a0f6ae

为什么Borg模式比Python中的Singleton模式更好

  •  68
  • u0b34a0f6ae  · 技术社区  · 17 年前

    为什么会这样 Borg pattern 胜过 Singleton pattern

    我这样问是因为我看不出他们有什么不同。

    博格:

    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()
    

    单身人士:

    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()
    

    这个状态必须被初始化。这里的单例实现更简单,因为我们 作为全球国家的建立。我发现Borg对象必须查询其内部状态以查看是否应该更新自身,这很尴尬。

    你的内在状态越差,情况就越糟。例如,如果对象必须侦听应用程序的拆卸信号以将其寄存器保存到磁盘,那么该注册也应该只执行一次,而使用单例更容易实现。

    6 回复  |  直到 9 年前
        1
  •  68
  •   Mirco Widmer    13 年前

    博格与众不同的真正原因在于子类化。

    如果您将一个borg子类化,则子类的对象与其父类对象具有相同的状态,除非您显式重写该子类中的共享状态。singleton模式的每个子类都有自己的状态,因此将生成不同的对象。

    在单例模式中,对象实际上是相同的,而不仅仅是状态(即使状态是唯一真正重要的东西)。

        2
  •  24
  •   Cristian Garcia    12 年前

    在python中,如果您想要一个可以从任何地方访问的唯一“对象”,只需创建一个类 Unique 只包含静态属性的, @staticmethod s、 及 @classmethod s你可以称之为独特模式。在这里,我实现并比较了3种模式:

    唯一的

    #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 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 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
    

    测验

    #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))
    

    输出:

    独生子女

    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
    

    在我看来,唯一的实现是最简单的,其次是Borg,最后是Singleton,它的定义需要两个函数。

        3
  •  14
  •   André Laszlo    11 年前

    事实并非如此。在python中,通常不推荐这样的模式:

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

    使用类方法来获取实例,而不是构造函数。Python的元编程允许更好的方法,例如 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.instance
    
    class MyClass(object):
        __metaclass__ = Singleton
    
    print MyClass()
    print MyClass()
    
        4
  •  8
  •   Zed    17 年前

    类主要描述如何访问(读/写)对象的内部状态。

    在单例模式中,您只能有一个类,即您的所有对象将为您提供对共享状态的相同访问点。 这意味着,如果必须提供扩展API,则需要编写一个包装器,包装单例

        5
  •  8
  •   Lennart Regebro    17 年前

    只有在少数情况下,当你真的有差异时,它才会更好。比如当你子类的时候。Borg模式是极不寻常的,我在十年的Python编程中从未真正需要过它。

        6
  •  2
  •   volodymyr    8 年前

    此外,类Borg模式允许类的用户选择是共享状态还是创建单独的实例。(这是否是个好主意是另一个话题)

    class MayBeBorg:
        __monostate = None
    
        def __init__(self, shared_state=True, ..):
            if shared_state:
    
                if not MayBeBorg.__monostate:
                    MayBeBorg.__monostate = self.__dict__
                else:
                    self.__dict__ = MayBeBorg.__monostate
                    return
            self.wings = ..
            self.beak = ..