一、シングルトン
特殊なクラスで、このクラスは一度しかインスタンスオブジェクトを作成できず、インスタンスオブジェクトの初期値は最後のものが優先されます。
二、シングルトンパターン
すべてのクラスがインスタンス化される際に、同じメモリアドレスを指すようにするデザインパターンです。
三、シングルトンパターンの5つの実装方法
シングルトンパターンを設定する本質: 1)このインスタンスが存在するかどうかを判断する 2)存在する場合は、このインスタンスを返す;存在しない場合は、このインスタンスオブジェクトを作成する
1、__new__メソッドによる実装
class UniqueInstance:
_singleton_ref = None # 属性--インスタンスオブジェクトの参照を保存する(変数代入のようなもの)
def __new__(cls, *args, **kwargs):
if not cls._singleton_ref:
cls._singleton_ref = super().__new__(cls, *args, **kwargs)
return cls._singleton_ref
1、クラス属性を定義し、初期値をNoneに設定し、シングルトンオブジェクトの参照を記録するために使用します。 2、__new__メソッドをオーバーライドします。 3、クラス属性がNoneの場合、親クラスを呼び出してスペースを割り当て、クラス属性に結果を記録します。 4、クラス属性に記録されたオブジェクト参照を返します。
if条件判断はhasattr()関数でも使用できます。
hasattr()関数は、オブジェクトが対応する属性やメソッドを含んでいるかどうかを判断します。パラメータはオブジェクトと文字列で、文字列がオブジェクトの属性値またはメソッド名の場合、関数はTrueを返し、そうでない場合はFalseを返します。
class DataContainer:
def __init__(self, identifier): # インスタンスメソッドの初期化
self.identifier = identifier # インスタンス属性
def __new__(cls, *args,**kwargs):
if not hasattr(cls, '_instance'): # hasattr(cls, '_instance')がFalseの場合、オブジェクト_instanceが存在しないことを示し、この条件not hasattr(cls, '_instance')が真になるため、ifコードブロック内の内容が実行されます
cls._instance = super(DataContainer, cls).__new__(cls) # 親クラスの__new__メソッドを呼び出してインスタンスを作成
return cls._instance
# 使用例
obj1 = DataContainer('initial_data')
obj2 = DataContainer('updated_data')
print(obj1.identifier) # 'updated_data'を出力
print(obj2.identifier) # 'updated_data'を出力
2、@classmethodによる実装
class SingletonManager:
_singleton = None
@classmethod
def get_singleton(cls):
if cls._singleton is None:
cls._singleton = cls()
return cls._singleton
3、デコレータによる実装
def singleton_decorator(target_class):
instances = {}
def wrapper(*args, **kwargs):
if target_class not in instances:
instances[target_class] = target_class(*args, **kwargs)
return instances[target_class]
return wrapper
@singleton_decorator
class Configuration:
pass
4、モジュールインポートによる実装
# singleton_module.py
class SingletonObject:
pass
# 使用時
import singleton_module
my_singleton = singleton_module.SingletonObject()
Pythonのモジュールは自然なシングルトンパターンです。なぜなら、モジュールが初めてインポートされる際、コードは一度だけ実行され、以降のインポートでは再実行されないからです。
5、メタクラスによる実装
class SingletonMeta(type):
_registry = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._registry:
cls._registry[cls] = super().__call__(*args, **kwargs)
return cls._registry[cls]
class SingletonEntity(metaclass=SingletonMeta):
pass