インスタンス生成時にオブジェクトが指定されてインスタンスが一つしかないことを保証します。インスタンス生成にはメモリが必要で作成に若干時間を要します。
シングルトンを使えば同じプロセス内であれば再度インスタンスが生成されないようにすることが可能です。
使用例
データベースへアクセスするためのインスタンス
データベースのURL、ID、パスワードなどを保持します。こういうのは誰が使うにしても同じ情報なのでインスタンスは一つしか必要ないです。
Objectを作成するFactory
作成されるオブジェクト側はインスタンスは人によって分けられるのは普通ですが、作成する側のFactoryクラスの方は一つで問題ないです。
シングルトンじゃない実装
1 2 3 4 5 6 7 8 9 |
class NonSingleTon: pass a = NonSingleTon() b = NonSingleTon() print(a == b) # False |
シングルトンな実装
もし、値を設定したい場合はsetterを使って設定します。ただ、この書き方だとsuperなどの構文が出てきてイマイチソースの内容が分かりづらいというデメリットがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class SingleTon: _instance = None def __init__(self): self.__url = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance @property def url(self): return self.__url @url.setter def url(self, url): self.__url = url a = SingleTon() b = SingleTon() print(a == b) # True |
__new__
インスタンスを生成した時に呼ばれます。最初に呼び出した場合は_instanceがNoneになっているので、生成して返します。2回目に呼び出した場合は既存のインスタンスを返しています。
シングルトンな実装2
Javaなどのほかの言語のデザインパターン本で使われている書き方です。Javaではコンストラクタをprivateにすることで直接newするのを防ぎますが、Pythonではコンストラクタをプライベートにすることができませないのでコンストラクタを利用した場合はエラーを返すようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class Singleton: __instance = None def __init__(self): raise RuntimeError("このクラスのコンストラクタは呼び出せません") @classmethod def get_instance(cls, url=None): if cls.__instance is None: cls.__instance = cls.__new__(cls) if url: cls.__instance.__url = url return cls.__instance @property def url(self): return self.__url @url.setter def url(self, url): self.__url = url a = Singleton.get_instance("htp://aaa") b = Singleton.get_instance() print(a == b) print(id(a), id(b)) print(a.url, b.url) a.url = "http://bbb" print(a.url, b.url) |
この記事へのコメントはありません。