cxi単例モードの実現方法


単例モードは大体すべての設計モードの中で一番簡単なものです。面接の時、どのデザインパターンを熟知しているかと聞かれたら、一番最初に答えたのは単例モードかもしれません。
シングルモデルの実現は、餓漢式と怠け者式の2種類に分けられます。前者は静的なコンストラクタの実行時にすぐに実用化され、後者はプログラム実行中に初めて必要とされた時に実行されます。両者にはそれぞれの適用シーンがあり、実現方法も簡単で、唯一の設計時に考慮するべき問題は、実装時にスレッドの安全を保証する必要があるということです。
餓鬼タイプ
餓漢式実現は簡単で、静的コンストラクタにおいて直ちに実用化される。

public class Singleton
{
  private static readonly Singleton _instance;
  static Singleton()
  {
    _instance = new Singleton();
  }

  public static Singleton Instance
  {
    get
    {
      return _instance;
    }
  }
}
単一の例を保証するためには、readonlyキーステートメントのインスタンスは変更されないことに留意されたい。
以上の書き方は簡単に書くことができます。

public class Singleton
{
  private static readonly Singleton _instance = new Singleton();
  public static Singleton Instance
  {
    get
    {
      return _instance;
    }
  }
}
ここでのnew Singleton() は、静的コンストラクタにおける実装と同等である。C菗7にはさらに以下のように簡単に書くことができます。

public class Singleton
{
  public static Singleton Instance { get; } = new Singleton();
}
一つのコードで解決しました。この表記は、実用化も標準的な静的構造関数で行います。餓漢式の需要なら、この実現は一番簡単です。これはスレッドの安全問題がありますか?複数のスレッドが同時にSingleton.Instanceを呼び出すと、複数のインスタンスが実装されますか?いいえ、CLRはすべての静的構造関数がスレッドで安全であることを保証しています。
このように書いてはいけません。

public class Singleton
{
  public static Singleton Instance => new Singleton();
}

//    :
public class Singleton
{
  public static Singleton Instance
  {
    get { return new Singleton(); }
  }
}
このようにすると、呼び出しごとに新しいインスタンスが作成されます。
なまけ者根性
怠け者式の一例実現にはスレッドの安全を考慮する必要があります。まずは古典的なスレッドの安全を考慮した一列モードの実現コードを見てください。

public sealed class Singleton
{
  private static volatile Singleton _instance;
  private static readonly object _lockObject = new Object();

  public static Singleton Instance
  {
    get
    {
      if (_instance == null)
      {
        lock (_lockObject)
        {
          if (_instance == null)
          {
            _instance = new Singleton();
          }
        }
      }
      return _instance;
    }
  }
}
ネットでC〓〓〓の一例のモードを捜索して、大部分がこのようにロックを使ってスレッドの安全を確保する書き方で、これは経典の標準の一例のモードの書き方で、大丈夫で、とても安心します。ロックの中で外部はすべて一回のinstanceの空の判断をして、双保険、十分にスレッドの安全と単例性を保証します。でも、この書き方は面倒くさいようです。書き間違えやすいです。C菙3.5の時に、もっといい書き方ができました。Lazyを使います。
サンプルコード:

public class LazySingleton
{
  private static readonly Lazy<LazySingleton> _instance =
    new Lazy<LazySingleton>(() => new LazySingleton());

  public static LazySingleton Instance
  {
    get { return _instance.Value; }
  }
}
呼び出しの例:

public class Program
{
  public static void Main()
  {
    var instance = LazySingleton.Instance;
  }
}
Lazy<T>を使用して、オブジェクトの実例化を第1回の呼び出し時に実行し、そのValue属性にアクセスしてインスタンスを作成して取得し、Lazy<T>インスタンスを読み出すValue属性は、スレッドの安全を保証するために、一度だけ実装コードを実行します。
はい、楽しいコーディングをしてください。
以上はcxi単例モードの実現方法の詳細です。cxi単例モデルに関する資料は他の関連記事に注目してください。