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


# はじめに  
本エントリーは某社内で実施するデザインパターン勉強会向けの資料となります。  
本エントリーで書籍「[Java言語で学ぶデザインパターン入門](http://www.hyuki.com/dp/)」をベースに学習を進めますが、サンプルコードはC#に置き換えて解説します。  
  
第1回：[Iteratorパターン](http://qiita.com/Nuits/items/800f080d44b52e1cae18)  
第2回：[Adapterパターン](http://qiita.com/Nanakusajp/items/747d1913b1e8bea8d340)  
第3回：[Template Methodパターン](http://qiita.com/_kyam/items/9b5722e6a9635af6e18b)  
第4回：[Factory  Methodパターン](http://qiita.com/ayayo/items/3eece04bbc4b7504179a)  

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


---

# サンプルプログラムのクラス図  
Singletonパターンを使用したサンプルプログラムのクラス図を紹介します。
 
![UML_Singleton.JPG](https://qiita-image-store.s3.amazonaws.com/0/199196/da011d78-1476-8b8f-63a7-06958f7ffc6d.jpeg)
  
  
---

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

---

# Singletonクラス  
Singletonクラスでは、インスタンスは1つしか作られません。
Singletonクラスでは、staticフィールド(クラス変数)として_singletonが定義され、それをSingletonクラスのインスタンスで初期化しています。この初期化はSingletonクラスのロード時に1度だけ行われます。   
Singletonクラスのコンストラクタはprivateになっています。
これはSingletonクラス外からコンストラクタを呼び出すことを禁止するためです。
したがって、もし、  

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

```csharp
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という式でチェックしています。 
  
```csharp
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  

---