Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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

by Keenag
1 / 13

はじめに

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

本エントリーで書籍「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


Keenag
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした