#C#
#Singleton
#デザインパターン

デザインパターン勉強会 第5回:Singletonパターン

はじめに

本エントリーは某社内で実施するデザインパターン勉強会向けの資料となります。

本エントリーで書籍「Java言語で学ぶデザインパターン入門」をベースに学習を進めますが、サンプルコードはC#に置き換えて解説します。

第1回:Iteratorパターン

第2回:Adapterパターン

第3回:Template Methodパターン

第4回:Factory Methodパターン


Singletonパターンとは

指定したクラスのインスタンスが1つしか存在しないことを保証するデザインパターンです。  


サンプルプログラムのクラス図

Singletonパターンを使用したサンプルプログラムのクラス図を紹介します。

UML_Singleton.JPG


各クラスの役割

クラス名 役割
Singleton インスタンスが1つしか存在しないクラス
ConfirmSingleton 動作テスト用のクラス

Singletonクラス

Singletonクラスでは、インスタンスは1つしか作られません。
Singletonクラスでは、staticフィールド(クラス変数)として_singletonが定義され、それをSingletonクラスのインスタンスで初期化しています。この初期化はSingletonクラスのロード時に1度だけ行われます。

Singletonクラスのコンストラクタはprivateになっています。
これはSingletonクラス外からコンストラクタを呼び出すことを禁止するためです。
したがって、もし、

new Singleton()  

という式がこのクラス外にあったとしてもコンパイルエラーとなります。

using System;

namespace SingletonSample
{
    public class Singleton
    {
        private static Singleton _singleton = new Singleton();

        private Singleton()
        {
            Console.WriteLine("インスタンスを生成しました。");
        }

        public static Singleton GetInstance()
        {
            return _singleton;
        }
    }
}

ConfirmSingletonクラス

ConfirmSingletonクラスは、Singletonを利用しているクラスです。
ここでは、SingletonクラスのgetInstanceメソッドを使ってSingletonのインスタンスを得ています。
getInstanceメソッドは2回呼び出されています。戻り値はそれぞれobj1とobj2に代入しています。
確かに同じインスタンスが得られているかどうかを、obj1==obj2という式でチェックしています。

using System;

namespace SingletonSample
{
    public class ConfirmSingleton
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Start");
            Singleton obj1 = Singleton.GetInstance();
            Singleton obj2 = Singleton.GetInstance();

            if (obj1 == obj2)
            {
                Console.WriteLine("obj1とobj2は同じインスタンスです。");
            }
            else
            {
                Console.WriteLine("obj1とobj2は同じインスタンスではありません。");
            }

            Console.WriteLine("End");
            Console.ReadLine();
        }
    }
}


実行結果

先のMainを実行した結果は以下の通りです。

Start.
インスタンスを生成しました。
obj1とobj2は同じインスタンスです。
End.

どんなクラスをSingletonにするケースがあるか

  • キャッシュクラス
    ファイルへのアクセス処理は非常に負荷がかかり、処理速度に影響を及ぼします。
    ファイルの内容の更新は行われないが、参照は頻繁に行われるようなファイルを毎回読み込むのは、効率が良いとは言えません。
    そんなとき、 キャッシュ機構をもつクラスをSingleton化することで、アプリケーションが終了しない限り、キャッシュに保持されたデータをあらゆる局面で取り出すことができるようにできます。

参考URL :
http://www.nulab.co.jp/designPatterns/designPatterns2/designPatterns2-1.html


Singletonは使うべきはないという意見もある

本エントリーでは取り上げませんが、以下のサイトでSingletonパターンを使うべきではない理由がまとめられています。興味のある方はご覧になってみてください。

http://qiita.com/mo12ino/items/abf2e31e34278ebea42c


まとめ

  • Singletonパターンはインスタンスが1つしか存在しないことを保証するデザインパターン
  • インスタンスを得るためのstaticメソッドを用意する
  • クラスの外からnewされないようにコンストラクタをprivateにする

サンプルコード

以下に公開しています。

https://github.com/Keenag/SampleCode