本文へスキップ
BecomeCoder

C#デザインパターンコース · 第1章 デザインパターン · レッスン4

生成④:Singleton

ブラウザで完結

導入

Singletonは「そのクラスのインスタンスは常に1つだけ」を保証するパターンです。設定・ログ・接続プールなど、アプリ全体で共有したい唯一の存在に使います。

図解

flowchart TB
    A["どこから呼んでも"] --> S["AppConfig.Instance"]
    B["別の場所から呼んでも"] --> S
    S --> ONE["常に同じ1つの実体"]
    style ONE fill:#e8f5e9

サンプル

唯一の存在そのもの(AppConfig.cs)と、それを取り出す側(Program.cs)に分けます。

1. 唯一のインスタンスを持つクラス(AppConfig.cs)。コンストラクタをprivateにするのが要です。

public class AppConfig
{
    // static readonly で唯一のインスタンスを保持
    public static AppConfig Instance { get; } = new AppConfig();

    private AppConfig() { }   // コンストラクタを private にして外部の new を禁止

    public string AppName { get; set; } = "";
}

2. 使う側(Program.cs)。どのファイル・どの行から取っても同じ実体が返ります。

// どこから取得しても同じ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(同一の実体)
  • コンストラクタをprivateにして外部からのnewを禁止する
  • staticなInstanceで唯一のインスタンスを公開する
  • ファイルが分かれていても実体は1つ。裏を返せばどのファイルからも触れるグローバル状態になる
  • そのため乱用はテストを難しくする。実務では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です。

実際に動かしてみよう

このレッスンのサンプルは、実務と同じように役割ごとの .cs ファイルへ分けてあります。下のエディタは最初からその複数ファイルが入った状態で、上のタブでファイルを切り替えられます。そのまま「▶ 実行」を押せば全ファイルをまとめてコンパイルして動かせるので、クラスを足したりファイルをまたいで書き換えたりしながら進めましょう(演習は本文のコードをコピーして Program.cs のタブに貼り付ければ試せます)。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。

次のレッスンへ →