PythonでSingletonパターンを実現する方法

プログラミング Python

Pythonでデザインパターンの「Singleton」を実現するにはクラスコンストラクターの「__new__()」でインスタンス生成を制御する必要があります。

Singleton パターン(シングルトン・パターン)とは、オブジェクト指向のコンピュータプログラムにおける、デザインパターンの1つで、そのクラスのインスタンスが1つしか生成されないことを保証するデザインパターンのことでです。
スポンサーリンク

PythonでSingletonパターンを実現する

PythonでSingletonパターンを実現するにはクラスコンストラクターの「__new__()」で初めてのインスタンス生成かどうかチェックして、初めての場合のみ新規にインスタンスを生成して返すようにします。

インスタンスとはオブジェクト指向言語においては、多くの場合クラスと呼ばれるものを元に作成したオブジェクトの実体のことです。

以下が具体的な実装方法です。

import sys

#Singletonクラス定義
class Singleton:
    singleton = None
    name = None
    def __new__( cls, *args, **kwargs ):
        #1回目のクラス生成(クラスインスタンスが無ければ作成する)
        if cls.singleton == None:
            cls.singleton = super().__new__( cls )

        cls.name = 'My name is Taro.'

        #クラスのインスタンスを返す
        return cls.singleton

    def getName( self ):
        return str( self.name ) ;

    def setName( self, name ):
        self.name = str( name )

上記で__new__()メソッド内で一度目のインスタンスが生成されているかどうか

        if cls.singleton == None:

でチェックし、されてなければ

            cls.singleton = super().__new__( cls )

で生成します。

あとは呼ばれるたびに

        return cls.singleton

該当クラスのインスタンスを返すだけです。

上記のクラスが本当に1つしか生成されていないか確認するコードは

#クラスインスタンス化
s1=Singleton()
s2=Singleton()

#保存されているインスタンスのアドレス
print( s1 )
print( s2 )
print( '*************************' )
print( '変更前のs1のname=[' + s1.getName() + ']' )
print( '変更前のs2のname=[' + s2.getName() + ']' )

s1.setName( 'My name is Jiro.' )

print( '*************************' )
print( '変更後のs1のname=[' + s1.getName() + ']' )
print( '変更後のs2のname=[' + s2.getName() + ']' )

で確認でき、実行結果は

<__main__.Singleton object at 0x0000022662FA3508>
<__main__.Singleton object at 0x0000022662FA3508>
*************************
変更前のs1のname=[My name is Taro.]
変更前のs2のname=[My name is Taro.]
*************************
変更後のs1のname=[My name is Jiro.]
変更後のs2のname=[My name is Jiro.]

になり、s1のnameを変更するとs2のnameも変更されいていることが確認できます。

まとめ

PythonでSingletonを実現するには他のプログラミング言語(C++やJava)などと異なり、デフォルトコンストラクターを上書きすることで実現するのではなく、__new__()コンストラクターで実現できます。

以上、PythonでSingletonパターンを実現する方法でした。

タイトルとURLをコピーしました