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

u0b*_*6ae 74 python singleton

为什么Borg模式Singleton模式更好?

我问,因为我没有看到它们导致任何不同.

博格:

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()
Run Code Online (Sandbox Code Playgroud)

辛格尔顿:

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()
Run Code Online (Sandbox Code Playgroud)

我想在这里显示的是服务对象,无论是作为Borg还是Singleton实现,都有一个非常重要的内部状态(它提供了一些基于它的服务)(我的意思是它必须是有用的东西,它不是Singleton/Borg只是为了有趣).

而且这个州必须被引入.这里的Singleton实现更直接,因为我们将init视为全局状态的设置.我发现Borg对象必须查询其内部状态以查看它是否应该自行更新.

你拥有的内部状态越多,情况就越糟糕.例如,如果对象必须侦听应用程序的拆除信号以将其寄存器保存到磁盘,那么该注册也应该只执行一次,使用Singleton会更容易.

Dav*_*ick 57

borg不同的真正原因归结为子类化.

如果您继承borg,则子类'对象具有与其父类对象相同的状态,除非您显式覆盖该子类中的共享状态.单例模式的每个子类都有自己的状态,因此会产生不同的对象.

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

  • 我没有说这是件坏事.这是对差异的一种无意见的观察.对困惑感到抱歉.有时单例会更好,例如,如果您通过id(obj)对对象id进行任何检查,即使这种情况很少见. (2认同)

Cri*_*cia 22

在python中如果你想要一个可以从任何地方访问的唯一"对象",只需创建一个Unique只包含静态属性,@staticmethods和@classmethods的类; 你可以称之为独特模式.在这里,我实现并比较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
Run Code Online (Sandbox Code Playgroud)

独生子

#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
Run Code Online (Sandbox Code Playgroud)

博格

#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
Run Code Online (Sandbox Code Playgroud)

测试

#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))
Run Code Online (Sandbox Code Playgroud)

输出:

辛格尔顿

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
Run Code Online (Sandbox Code Playgroud)

在我看来,Unique实现是最简单的,然后是Borg,最后是Singleton,其定义需要两个函数.


bay*_*yer 13

它不是.通常不推荐的是python中这样的模式:

class Singleton(object):

 _instance = None

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

 @classmethod
 def instance(cls):
  if cls._instance is None:
   cls._instance = cls(...)
  return cls._instance
Run Code Online (Sandbox Code Playgroud)

在哪里使用类方法来获取实例而不是构造函数.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()
Run Code Online (Sandbox Code Playgroud)

  • 最好/更差?那将取决于你的用例不会.我可以想到一些你希望像这样保存状态的情况. (5认同)
  • 这不是问题,@ MichaelDeardeuff.这是_intended behaviour_.它们应该是一样的.borg模式中的一个问题是,如果你在Borg .__ init__方法中添加一些初始化变量,比如`self.text =""`,那么就改变那个对象,如`borg1.text ="blah"`然后实例化一个新的对象`borg2 = Borg()" - wham!在__init__中初始化的所有borg1属性都是whiped.所以实例化是不可能的 - 或者更好:在Borg模式中,你不能在__init__方法中初始化成员属性! (5认同)

Zed*_*Zed 8

类基本上描述了如何访问(读/写)对象的内部状态.

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

在borg模式中,您可以扩展基础"borg"类,从而更方便地扩展API以满足您的需求.


Len*_*bro 8

只有在你真正有所不同的少数情况下才会更好.就像你的子类.Borg模式非常不寻常,我在Python编程的十年里从来没有真正需要它.