2014-12-19 40 views
4

我已經看到了幾種在Python中創建單例的方法,但它們似乎都有一些缺點或其他。我自己發明了一種方法,我想知道它有什麼問題:)。自毀式構造函數== Singleton?

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只能被實例化一次,儘管其他一些機制需要將單個實例放在客戶端可以訪問的地方。

這種方法還有其他缺點嗎?

+1

一個小問題:'__init__'確實不是構造函數,它是一個初始化函數 - python結構是'__new__'。而且沒有什麼可以阻止我用自己的'__init__'方法繼承A,所以'A .__ init__'永遠不會被執行。 –

+3

你處理單例的缺點是,如果我只看A類的代碼,那麼我就不能說它是單身的。 – Dunes

+0

@ TonySuffolk66這個想法是否會劫持「A .__ init__」在子類中執行?你仍然只能執行一次,對吧? –

回答

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) 

的作品。

+0

有趣。 +1爲具體的工作示例。 –

相關問題