- Singletonパターン (1)
- Singletonパターン (2) - ぜ〜んぶクラスメソッド
- Singletonパターン (3) - モジュール
- Singletonパターン (4) - メタクラスを使った方法
- Singletonパターン (5) - Borgの方法
Singletonにはサブクラス化したとき、
のどちらにするのか、という問題が生じます。
Pythonでは、Borgの方法というものを使えば、このどちらにするのかを、自由に選択できます。
なお、Borgの方法は『Rubyによるデザインパターン』ではなく『Pythonクックブック』から、拝借しました。
class Borg(object): _shared_state = {} def __new__(cls, *a, **kw): instance = object.__new__(cls, *a, **kw) instance.__dict__ = cls._shared_state return instance def set_name(self, name): self.name = name def get_name(self): return self.name class Example(Borg): #基底クラスと状態を共有する pass class Example2(Borg): #基底クラスと状態を共有しない _shared_state = {} if __name__ == "__main__": s1 = Borg() s2 = Example() s3 = Example2() s4 = Example2() s1.set_name("egg") s2.set_name("spam") s3.set_name("hoge") s4.set_name("piyo") print s1, s1.get_name() print s2, s2.get_name() print s3, s3.get_name() print s4, s4.get_name()
Pythonの「クラスの属性=辞書」という特性を利用します。
__new__で、インスタンスの属性辞書を、ある特定の辞書に変更します。
BorgではSingletonと違って、インスタンスの唯一性は保たれません。
a = Borg() b = Borg() print a is b # => None
しかし必要なのは、インスタンスそのものの同一性ではなく、振る舞いの同一性なので、Borgの方法はSingletonの代替になりうるのです。