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

# Singletonパターン

　Singletonはデザインパターンの１つで、クラスのインスタンスオブジェクトをただ１つにすることができます。これを利用することで、例えばデータベースにコネクションするためのクラスを１つにすることで、複数のインスタンスが同時にデータベースを操作しないという前提でコードを書けるようになるため同期やメモリ内のデータを管理することができるようになります。
　また、並行性の制御も簡単になります。例えば一意なドキュメントIDを予約するドキュメントがある場合、その作業をするユーティリティは１つである方が良いので、Singletonパターンを採用すると良いです。

# `__new__()`メソッドをオーバーライトする方法

　`__new__()`メソッドをオーバーライトして以下のように実装できます。

```python
class Singleton(object):
    _instance = None
    
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls, *args, **kwargs)
            
        return cls._instance
```

　このクラスから複数のインスタンスを生成し、IDを確認してみます。同じオブジェクトが作られていることが確認できると思います。

```python
obj1 = Singleton()
obj2 = Singleton()

print(id(obj1) == id(obj2))
# True

print(obj1 == obj2)
# True
```

　しかし、この方法は落とし穴があります。このクラスを継承したサブクラスを作り、それぞれインスタンスを生成してみます。

``` python
class SubSingleton(Singleton):
    pass

print(Singleton())
# <__main__.Singleton object at 0x10cfda9e8>

print(SubSingleton())
# <__main__.Singleton object at 0x10cfda9e8> 
```

　この結果を見ますと、サブクラスのインスタンスはベースクラスのインスタンスとして生成されてしまいます。それだけではなくインスタンスの生成順序によって挙動が変わってしまう問題もあります。

``` python
class SubSingleton(Singleton):
    pass

print(SubSingleton())
# <__main__.SubSingleton object at 0x10c3f57b8>

print(Singleton())
# <__main__.Singleton object at 0x10c3f5748> 
```

　順序によって振る舞いが異なると動作を予測するのが難しくなってしまいます。特に大規模なアプリケーションになるとデバッグが困難になってしまいます。ユーザの動作やimportの順番によってアプリケーションが破壊されてしまうかもしれないからです。
　通常、Singletonクラスは継承して使うことは避けるべきです。`__new__()`メソッドをオーバーライトする方法もサブクラスを作るようなことをしなければ安全な実装ではあります。言語によっては、例えばC#ではsealed修飾子を使うことで継承を禁止することができます。しかし、Pythonは継承を禁止することができないので誤って実装する恐れがあります。そのため継承される場合も考えた方がより安全です。

# メタクラスを使用する方法

 メタクラスの`__call__()`メソッドをオーバーライトすることでクラスをSingletonにすることができます。

```python
class MetaSingleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

class Singleton(metaclass = MetaSingleton):
    pass

class SubSingleton(Singleton):
    pass

print(Singleton() == Singleton())
# True

print(SubSingleton() == SubSingleton())
# True

print(Singleton())
# <__main__.Singleton object at 0x10ce84ef0>

print(SubSingleton())
# <__main__.SubSingleton object at 0x10ce84e48>
```

``` python
# 生成順序を逆にしてみる
print(SubSingleton())
# <__main__.SubSingleton object at 0x10ce84c18>

print(Singleton())
# <__main__.Singleton object at 0x10ce84cf8>
```

　上の実装を確認しますと、各クラスから生成されるインスタンスは１つだけで、生成順序にも依存しない実装をすることができますので、`__new__()`メソッドをオーバーライトする方法よりも安全だと思います。

# Borgで置き換える実装
　
　この方法は「Python クックブック」の著者であるAlex Martelliという方が提案した方法です。Singletonのように振る舞いをしますが、構造が異なっており、`__dict__`で全てのクラスインスタンスを共有するようにしています。これはBorg、またはMonostateと呼ばれます。

``` python
class Borg(object):
    _state = {}
    def __new__(cls, *args, **kwargs):
        ob = super().__new__(cls, *args, **kwargs)
        ob.__dict__ = cls._state
        return ob

print(Borg() == Borg())
# False
```

　Borgクラスを複数作ると別のインスタンスができます。それでもSingletonの代替として使えるのは複数のインスタンスが１つのように振る舞うからです。Singletonは１つのインスタンスを保証しますが、それ以上に重要なのは振る舞いを１つであることを保証することです。ですので、振る舞いの唯一性を保証できるBorgはSingletonの代替となります。
　ですが、この方法にも罠があります。サブクラスに置ける問題を解決することができますが、サブクラスの実装に依存してしまっています。例えば、サブクラスで`.`で属性を取得するときの処理をする`__getattr__`をオーバーライトしていた場合はBorgはうまく動作しなくなってしまいます。

# 簡潔な実装法

　ここまで様々な方法を紹介しましたが、最も簡単な方法は関数を持ったモジュールを用意することです。なぜなら、Pythonのモジュールは元々Singletonオブジェクトだからです。上記の実装方法が必要になるのはJavaのようなフレームワークを使っている場合です。ですので、特別の事情がない限りはSingletonパターンは必要がないと思います。

# 参考
- エキスパートPythonプログラミング改訂2版
  - https://www.amazon.co.jp/dp/4048930613/
- アジャイルソフトウェア開発の奥義 第2版 オブジェクト指向開発の神髄と匠の技 
  - https://www.amazon.co.jp/dp/4797347783/