メインコンテンツへスキップ

3言語でシングルトンパターンを実装

··2 分
遠瀬緑(Midry)
著者
遠瀬緑(Midry)
ゲーム開発者

シングルトンパターンとは
#

インスタンスの存在を 一つだけ 許すような実装のことを シングルトンパターン と言います。例えば「ゲームのセーブデータを管理するクラス」があるとします。このクラスのインスタンスを、それぞれ必要になった箇所で作っていたらどうなるでしょうか?

そう、あるインスタンスで呼んだセーブは他のインスタンスには適用されません。「セーブファイルを毎回覗けばいいじゃん」と思うかもしれませんが、それは処理速度的な問題があります。

そういう時に活躍するのがシングルトンパターンです。全ての箇所で「同じインスタンス」を扱っていれば、全ての変更を共有できます。素晴らしいですね。

今回はそんなシングルトンパターンの書き方を、僕が扱えるオブジェクト指向言語である

  • 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__はインスタンス生成前に呼ばれます。こいつをハックしていい感じにします。