読者です 読者をやめる 読者になる 読者になる

Singletonパターン (1)

python デザインパターン

Rubyによるデザインパターン』(ラス・オルセン著 ピアソン・エデュケーション刊)の例をPythonに変換して書いています。目次

Singletonパターンは「インスタンスが同時に2個以上存在しない」クラスを作るパターンです。

正直、Singletonを何時使うのか、私には分かりません。別に無くても良いように思えます。

しかし、Singletonは有名なようです。「python singleton」で検索すると、例がウジャウジャ出てきます。「python strategy」など、このサイトが上から4番目に上がるほどなのに・・・。

まずは、古典的なSingletonパターンの実装です。

#いわゆるSingleton
class Singleton(object):
    _instance = None
    def __new__(cls, *a, **kw):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *a, **kw)
        return cls._instance
    
    def set_name(self, name):
        self.name = name
    
    def get_name(self):
        return self.name
    
s1 = Singleton()
s2 = Singleton()
s1.set_name("egg")
s2.set_name("spam")

print s1.get_name() #=> spam
print s2.get_name() #=> spam


Singletonパターンの問題は、サブクラス化の時に顔を出します。

class Example(Singleton):
    def set_name(self, name):
        Singleton.set_name(name*2)

a = Singleton()
b = Singleton()
c = Example()
c.set_name("aaaa")

print c.get_name() #=> aaaa
#あれ〜?

Singletonクラスは2個以上のインスタンスを持ちません。

つまり、Singletonのインスタンスが既に存在するのに、
新たにインスタンスを作ろうとしても、既存のSingletonのインスタンスが返されます。

そして、サブクラスExampleのインスタンスは、同時にSingletonのインスタンスでもあります。

よってSingletonのインスタンスが既にあるときに、
Exampleのインスタンスを作ろうとしても、既存のSingletonのインスタンスが返されるのです。

つまり・・・

a = Singleton()
b = Singleton()
c = Example()

print c #=> <__main__.Singleton object at 0x00B014F0>


また、Singletonパターンのどこからでも同じ物を参照できるという性質は、グローバル変数と同じです。

Singletonのグローバル変数より優れている点は、インスタンス最大数を調整できる事です。

Singleton.__new__をちょっと改良すれば、高々20しかインスタンスが存在しないクラスを作るのは簡単です。

しかし、プログラムの結合度が増すという点では同じです。Singletonを使う前に、よくよく検討するべきでしょう。