導入
Singletonは「そのクラスのインスタンスは常に1つだけ」を保証するパターンです。設定・ログ・接続プールなど、アプリ全体で共有したい唯一の存在に使います。
図解
flowchart TB
A["どこから呼んでも"] --> S["AppConfig.Instance"]
B["別の場所から呼んでも"] --> S
S --> ONE["常に同じ1つの実体"]
style ONE fill:#e8f5e9
サンプル
// どこから取得しても同じ1つのインスタンス
AppConfig.Instance.AppName = "BecomeCoder";
Console.WriteLine(AppConfig.Instance.AppName); // BecomeCoder
var a = AppConfig.Instance;
var b = AppConfig.Instance;
Console.WriteLine(ReferenceEquals(a, b)); // True(同一の実体)
class AppConfig
{
// static readonly で唯一のインスタンスを保持
public static AppConfig Instance { get; } = new AppConfig();
private AppConfig() { } // コンストラクタを private にして外部の new を禁止
public string AppName { get; set; } = "";
}
- コンストラクタを
privateにして外部からのnewを禁止する staticなInstanceで唯一のインスタンスを公開する- ただし乱用は「どこからでも触れるグローバル状態」になりテストを難しくする。実務ではDIコンテナに
Singleton登録する方式が主流
演習
Counter.Instance.Increment();
Counter.Instance.Increment();
Console.WriteLine(Counter.Instance.Value); // 2
// TODO: インスタンスが常に1つの Counter を定義してください
// (Instance プロパティ / private コンストラクタ / Increment() / Value)
___
- 期待される出力:
2
ヒント1を見る
public static Counter Instance { get; } = new Counter(); private Counter() { }
ヒント2を見る
class Counter { public static Counter Instance { get; } = new Counter(); private Counter() { } public int Value { get; private set; } public void Increment() => Value++; }
まとめ
- Singletonはインスタンスを常に1つに保証する
privateコンストラクタ+static Instanceで実現- 乱用はグローバル状態化するため、実務ではDI管理が主流
次回: 構造パターンへ。互換性をつなぐAdapterとBridgeです。