GoF本 Singleton

GoFデザインパターン勉強メモ

まとめ

  • クラスから生成されるオブジェクトを1つに絞る

モチベーション

  • オブジェクトがただ1つであることが重要なケースがある

      • ファイルシステム
      • ウィンドウ
  • 「ただ一つのオブジェクト」の管理をどうするか

    • グローバル変数

      • newで第二第三のインスタンスを作れてしまうことを防げない
    • クラス自身に管理させる

      • これだ

つかいどころ

  • クラスのオブジェクトが1つでなければならない
  • クライアントコードからアクセスできる
  • 派生クラスを作って拡張可能

功罪

  • 唯一のオブジェクトへのアクセスコントロール
  • グローバル変数などの手法とくらべ、名前空間を汚さずに済む
  • 派生クラスを作って拡張可能

    • Strategyをシングルトンで作って、他のクラスのオブジェクトをカスタマイズするなど
  • オブジェクトの数を細やかに制御可能

    • マルチトンもできる

      • どういうときに使うんだろう
  • クラス自体をシングルトンとして使うよりも柔軟
    例) Mathクラス

    • クラスだとできないこと

      • マルチトン
    • クラスメソッドだとできないこと

      • オーバライド

        • PHPなんかだとできる
        • C++なんかだとできない
        • というかクラスが第一級オブジェクトでない限り普通できないと思うぞ
  • テストがしづらいことで悪名高い

実装面

  • 生成されるオブジェクトをただ一つに

    • 遅延初期化・メモ化
    • コンストラクタはprotectedに
  • 派生

    • 派生クラスの定義自体はどってことない
    • 派生クラスの知識の取り回しが問題になる

      • Singleton::Initialize()をオーバライド

        • リンク時にすべて決まってしまう
        • 実行時の柔軟性に欠ける
      • Singleton::Initialize()の中で分岐

        • ハードコーディングされるのでNG
      • Singletonクラス名->Singletonオブジェクトのカタログ(辞書)をつくる

        • PrototypeパターンのpartCatalogみたいなかんじ
        • 環境変数をキーに、所望のSingletonオブジェクトを返す感じ
    • Singletonカタログへの登録は誰がやる?

      • 各Singleton派生クラス自身がコンストラクタで行う
      • コンストラクタを呼ばないと登録されない
    • どこでコンストラクタ呼ぶの?

      • C++の例: Singleton派生クラスを定義するファイルで、staticグローバル変数を定義する
        static DerivedSingleton theSingleton;

        • staticグローバル変数は他のファイルから見えないので、名前空間を汚さない
    • 短所: 使われないSingleton派生もインスタンシエートされてしまう

用例

  • メタクラス

    • クラスのクラス
    • メタクラスのインスタンスはクラス
    • 同じクラスを何個も作らないので、メタクラスはシングルトンクラスである
  • 他のパターンとの協調

関連するパターン

いっぱいある

生成のパターンでは

  • AbstractFactory
  • Builder
  • Prototype