【问题标题】:Self-destructing constructor == Singleton?自毁构造函数 == 单例?
【发布时间】:2014-12-19 21:28:25
【问题描述】:

我已经看到了一些在 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 来实现的,Singleton 然后实例化它,然后通过使其构造函数引发运行时异常来阻碍它。我可以看到的主要缺点是这种模式只会阻止创建更多实例,但不能保证那里只有一个实例。它还可以完全阻碍任何课程,这可能是个坏主意。

这两个缺点可以通过将行为非抽象到每个想要成为单例的类中来解决。例如,blocked 的定义及其对self.__init__ 的赋值可以是A 的构造函数的最后几行。然后A 只能被实例化一次,尽管其他一些机制需要将单个实例放置在客户端可以访问它的地方。

这种方法还有其他缺点吗?

【问题讨论】:

  • 一个小点:__init__ 真的不是构造函数,它是一个初始化器——python 构造是__new__。没有什么可以阻止我用它自己的 __init__ 方法对 A 进行子类化 - 所以永远不会执行 A.__init__
  • 您处理单例的方式的缺点是,如果我只查看 A 类的代码,那么我将无法判断它是单例。
  • @TonySuffolk66 是否会劫持A.__init__ 以便在子类中执行?你仍然只能执行一次,对吧?
  • @Dunes,好点子。自毁初始化程序(不是构造函数!:-D)的不太抽象的方法也可以解决这个问题,对吧?
  • 如果有一个实例,则让单例的构造函数返回唯一实例,或者创建一个实例并在还没有实例时返回它,而不是引发异常,这通常很有用。这允许在许多地方使用(单个)实例,这很有用,因为这种模式通常用于有效的全局对象。

标签: python design-patterns singleton


【解决方案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 是单例,我们不应该对它们进行子类化。” p>

但事情是这样的:

b = Singleton(B, 10, 20)
a = Singleton(A, 10)

有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 2015-08-06
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多