概要
@hyuki 先生著の『Javaで学ぶデザインパターン入門』(2004年、SB Creative)の1章ずつをベースに、サンプルコードをC#で置き換えながら勉強していく記事です。
※著者の @hyuki 先生には適切に書籍への参照を入れれば問題ない旨ご確認いただいています。
本題
Singletonパターン
第5回はSingletonパターンです。Singletonはインスタンスが1個しか存在しないことを保証するデザインパターンです。
特定クラスのnewを1回しか実行しないことで同様の結果は実現できませんが、それを設計で表現します。
サンプルコード
早速具体的な事例を見てみましょう。『Javaで学ぶデザインパターン入門』(2004年、SB Creative)に掲載されているコードをC#で(大体)書き換えます。
using System;
namespace SingletonPattern
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Start.");
// => Start.
Singleton obj1 = Singleton.GetInstance();
// => インスタンスを生成しました。
Singleton obj2 = Singleton.GetInstance();
if (obj1 == obj2)
{
Console.WriteLine("obj1とobj2は同じインスタンスです。");
// => obj1とobj2は同じインスタンスです。
}
else
{
Console.WriteLine("obj1とobj2は同じ違うインスタンスです。");
}
Console.WriteLine("End.");
// => End.
// 実行が一瞬で終わって確認できないので、キーの入力を待ちます
Console.ReadLine();
}
}
public class Singleton
{
private static Singleton singleton = new Singleton();
private Singleton()
{
Console.WriteLine("インスタンスを生成しました。");
}
public static Singleton GetInstance()
{
return singleton;
}
}
}
効能
- 特定のクラスに対し、インスタンスが1つしかないことを保証できる。
使用上の注意
- 非同期処理、マルチスレッド処理に関しては書き方によってインスタンスの単一性が保証されなくなってしまう。例えば、初期化をnullで行い、GetIncetance時にインスタンスの有無を判定してインスタンスを生成するとする。インスタンス生成前に別にインスタンス有無の判定が実行されるとインスタンスが複数生成されるのでコントロールしないといけない。
- Singletonクラスとまったく同じ機能を持つクラスをもう1つ作って、そちらを使ってしまったら意味ない。
- グローバル変数の代わりに使わない。(状態を持つSingletonはグローバル変数に等しい...)
- 乱用しない。
- I know where you live アンチパターンというアンチパターンがシングルトンを多用するアプリケーションで多く見られる。結合度に注意。
- 継承できないので肥大化する可能性がある。
- インスタンスはは本当に1つしか存在しえないのか考える。複数存在するケースもあるなぁ...ってなったら破綻する。
メモ
- Singleton: 要素を1個しか持たない集合のこと
関連しているパターン
- Abstract Factoryパターン
- Builderパターン
- Facadeパターン
- Prototypeパターン
感想や疑問
- この記事(シングルトンの賢い使用法)めっちゃ詳しい。使用法というよりは下手に使用するんでないみたいな雰囲気...
- グローバル変数として使ってしまってる感があります。
- 調べる限りもはや使うなくらいな雰囲気です。
- DIで改善できるケースもあるとのことなので調べます。
C#で学ぶデザインパターン入門
①Iterator
②Adapter
③Template Method
④Factory Method
⑤Singleton
⑥Prototype
⑦Builder
⑧AbstractFactory
⑨Bridge
⑩Strategy
⑪Composite Pattern
⑫Decorator Pattern