为什么Borg模式比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() 

辛格尔顿:

 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或Singleton,都有一个不平凡的内部状态(它提供了一些基于它的服务)(我的意思是它必须是有用的,它不是一个单一的/博格只是为了有趣)。

而这个国家必须被驯服。 这里的Singleton实现更直接,因为我们将init视为全局状态的设置。 我发现Borg对象不得不查询它的内部状态,看它是否应该更新自己。

你越有内在的状态越糟糕。 例如,如果对象必须收听应用程序的拆卸信号以将其注册保存到磁盘,那么该注册应该只进行一次,而使用Singleton则更容易。

博格不同的真正原因归结为子类。

如果你inheritance了一个borg,那么子类的对象与它们的父类对象具有相同的状态,除非你显式地重写了这个子类中的共享状态。 单例模式的每个子类都有自己的状态,因此会产生不同的对象。

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

在Python中,如果你想要一个独特的“对象”,你可以从任何地方访问,只需创build一个类只包含静态属性, @staticmethod@classmethod ; 你可以称之为唯一模式。 在这里我执行和比较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 

testing

 #SINGLETON print "\nSINGLETON\n" A = Singleton.getInstance() B = Singleton.getInstance() print "At first Bx = {} and Ax = {}".format(Bx,Ax) Ax = 2 print "After Ax = 2" print "Now both Bx = {} and Ax = {}\n".format(Bx,Ax) 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 Bx = {} and Ax = {}".format(Bx,Ax) Ax = 2 print "After Ax = 2" print "Now both Bx = {} and Ax = {}\n".format(Bx,Ax) 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 Bx = {} and Ax = {}".format(Bx,Ax) Ax = 2 print "After Ax = 2" print "Now both Bx = {} and Ax = {}\n".format(Bx,Ax) print "Are A and B the same object? Answer: {}".format(id(A)==id(B)) 

输出:

辛格尔顿

 At first Bx = 1 and Ax = 1 After Ax = 2 Now both Bx = 2 and Ax = 2 Are A and B the same object? Answer: True BORG At first Bx = 1 and Ax = 1 After Ax = 2 Now both Bx = 2 and Ax = 2 Are A and B the same object? Answer: False UNIQUE At first Bx = 1 and Ax = 1 After Ax = 2 Now both Bx = 2 and Ax = 2 Are A and B the same object? Answer: True 

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

不是这样。 一般不build议在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() 

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

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

在borg模式中,您可以扩展基础“borg”类,从而更方便地为您的口味扩展API。

只有less数情况下,你确实有所不同。 就像你子类一样。 博格模式是非常不寻常的,我从来没有在十年的Python编程中真正需要它。

而且,类似Borg的模式允许类的用户select是否要共享状态或创build单独的实例。 (不pipe这个可能是一个好主意是一个单独的话题)

 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 = ..