为什么Borg模式比单例模式在Python中更好

93 投票
6 回答
38497 浏览
提问于 2025-04-15 13:48

为什么Borg模式单例模式更好呢?

我问这个是因为我觉得它们的结果似乎没有什么不同。

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

单例模式:

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模式还是单例模式实现的服务对象,它都有一个不简单的内部状态(它是基于这个状态提供某种服务的)(我指的是它必须是有用的,不是为了好玩而存在的单例或Borg)。

而这个状态是需要初始化的。在这里,单例的实现更简单,因为我们把初始化当作全局状态的设置。我觉得Borg对象需要查询它的内部状态来决定是否更新自己,这样有点尴尬。

如果内部状态越多,这种情况就越糟糕。例如,如果这个对象需要监听应用程序的关闭信号来保存它的注册信息到磁盘,那么这个注册也应该只做一次,而用单例模式来处理会更简单。

6 个回答

17

其实不是这样的。一般来说,在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的元编程功能可以让你使用更好的方法,比如在维基百科上提到的那种:

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

在Python中,如果你想要一个可以从任何地方访问的独特“对象”,你只需要创建一个名为Unique的类,这个类只包含静态属性、@staticmethod@classmethod。你可以把它称为独特模式。下面我实现并比较了三种模式:

独特模式

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

#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模式,最后是单例模式,因为它需要两个函数来定义,显得有些复杂。

73

borg和其他模式不同的真正原因在于它的子类化。

如果你创建了一个borg的子类,那么这个子类的对象会和它父类的对象拥有相同的状态,除非你在子类中明确地覆盖了这个共享的状态。每个单例模式的子类都有自己的状态,因此会产生不同的对象。

而在单例模式中,这些对象实际上是完全相同的,不仅仅是状态相同(虽然状态才是最重要的部分)。

撰写回答