シングルトンパターンとは #
インスタンスの存在を 一つだけ 許すような実装のことを シングルトンパターン と言います。例えば「ゲームのセーブデータを管理するクラス」があるとします。このクラスのインスタンスを、それぞれ必要になった箇所で作っていたらどうなるでしょうか?
そう、あるインスタンスで呼んだセーブは他のインスタンスには適用されません。「セーブファイルを毎回覗けばいいじゃん」と思うかもしれませんが、それは処理速度的な問題があります。
そういう時に活躍するのがシングルトンパターンです。全ての箇所で「同じインスタンス」を扱っていれば、全ての変更を共有できます。素晴らしいですね。
今回はそんなシングルトンパターンの書き方を、僕が扱えるオブジェクト指向言語である
- C++
- C#
- Python
の三つに分けて紹介します。
C++ #
まずはC++で書いてみます。あくまでも僕の書き方ですが。
class _SaveData {
public:
~_SaveData() = default;
static _SaveData& GetInstance() {
static _SaveData instance; // staticなので一度だけ宣言、インスタンスが作成される
return instance;
}
private:
_SaveData() = default; // コンストラクタをprivateにすることで他でのインスタンス作成を禁止
// 以下は代入、コピー、所有権移動の禁止コード
_SaveData& operator=(const _SaveData&) = delete;
_SaveData& operator=(_SaveData&&) = delete;
_SaveData(const _SaveData&) = delete;
_SaveData(_SaveData&&) = delete;
};
inline auto& SaveData = _SaveData::GetInstance(); // インスタンスを作っておく
C# #
まあほぼ同様です。
class _SaveData {
private static _SaveData instance = new _SaveData(); // staticなので一度だけ宣言、インスタンスが作成される
public static _SaveData GetInstance() {
return instance;
}
private _SaveData(){} // コンストラクタをprivateにすることで他でのインスタンス作成を禁止
}
var SaveData = _SaveData.GetInstance();
Python #
Pythonなんてほぼ無法地帯、北センチネル島なのでシングルトンパターンなんて無用かもしれませんが、人と話すときのネタにはなるかもしれませんので一応。
class _SaveData:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
SaveData = _SaveData()
Python黒魔術の一つ、__new__はインスタンス生成前に呼ばれます。こいつをハックしていい感じにします。