我已经看到了在Python中创建单例的几种方法,但它们似乎都有一些缺点或其他缺点。我自己刚刚发明了一种方式,我想知道它有什么问题:)。
class Singleton(object):
def __init__(self, cls, *args, **kwargs):
self.instance = cls(*args, **kwargs)
def blocked(doppelganger, *args, **kwargs):
raise RuntimeError("singleton")
cls.__init__ = blocked
def getInstance(self):
return self.instance
class A(object):
def __init__(self, x):
self.x = x
a = Singleton(A, 10)
这可以通过将类交给Singleton
来实现,然后实例化它,然后通过使其构造函数引发运行时异常来阻塞它。我可以看到的主要缺点是这种模式只会阻止创建更多实例,但并不能保证只有一个实例。它根本就可以阻碍任何课程,这可能是一个坏主意。
这两个缺点可以通过将行为取消抽象到想要成为单身的每个类来解决。例如,blocked
的定义及其对self.__init__
的分配可以是A
构造函数的最后一行。然后A
只能被实例化一次,尽管其他一些机制需要将单个实例放在客户端可以到达的位置。
这种方法还有其他缺点吗?
答案 0 :(得分:1)
它打破了继承:
class Singleton(object):
def __init__(self, cls, *args, **kwargs):
self.instance = cls(*args, **kwargs)
def blocked(doppelganger, *args, **kwargs):
raise RuntimeError("singleton")
cls.__init__ = blocked
def getInstance(self):
return self.instance
class A(object):
def __init__(self, x):
self.x = x
class B(A):
def __init__(self, x, y):
super(B, self).__init__(x)
self.y = y
a = Singleton(A, 10)
b = Singleton(B, 10, 20) # Raises RuntimeError
在这种情况下:Singleton(B, 10, 20)
,会调用引发异常的A.__init__
。
编辑:为了澄清,您可能会认为“这是预期的。由于A是单身,我们不应该将它们子类化。”
但事情就是这样:
b = Singleton(B, 10, 20)
a = Singleton(A, 10)
作品。