web-dev-qa-db-ja.com

シングルトンインスタンスを作成するためのファクトリ

至る所にたくさんのシングルトンがあるレガシーコードがあります(C#で記述)。

シングルトンは、パターンのかなり「古典的な」実装です。

public class SomeSingleton
{
    private static SomeSingleton instance;

    private SomeSingleton()
    {
    }

    public static SomeSingleton Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new SomeSingleton();
            }

            return instance;
        }
    } 
}

スレッドの安全性は問題ではないため、ロックは使用されないことに注意してください。

コードをよりテストしやすくするために、あまり多くの変更を加えずに、このコードを変更して、別のクラス(ファクトリーまたは同様のパターン)でのシングルトンインスタンスの作成を委任したいと思います。

これは、テスト目的の「テスト」インスタンス、または現在使用されている実際のバージョンの作成に役立ちます。

これは一般的な方法ですか?このようなパターンへの参照が使用されていませんでした。

4
liortal

コメントで、ゲーム開発にUnityとMonoを使用していると言います。それはMicrosoft UnityではなくUnity3Dを意味していると思います。そのため、フォローしているシングルトンパターンを破棄し、代わりに依存関係注入を使用することをお勧めします。 unity3dフレームワークでZenjectを使用できると思います。

シングルトンクラスは、次のようなインターフェイスのインスタンスになるように変更されます。

public class IImportantInterface
{
  DoSomethingImportant();
}

public class MySingletonImplementation: IImportantInterface
{
  public void DoSomethingImportant()
  {
    Console.WriteLine("This is Important!");
  }
}


public class DoImportantStuff
{
    private readonly IImportantInterface _ImportantInterface;

    public DoImportantStuff(IImportantInterface importantInterface )
    {
    _importantInterface = importantInterface;
    }


    public void DoSomething()
    {
    _importantInterface.DoSomethingImportant();
    }

}

次に、起動ロジックでシングルトンインスタンスをZenjectに登録できます。

Container.Bind<IImportantInterface>().ToSingle<MySingletonImplementation>(); 

この概念についての良いブログ投稿はここにあります: http://www.unityninjas.com/code-architecture/dependency-injection/

3
WellerEE

これには、制御の反転が必要です。まず、SomeSingletonにインターフェイスを追加して、ISomeSingletonと言います。次に、ISomeSingletonのすべてのコンシューマーは、ISomeSingletonのコンストラクターパラメーターを取得します。

例:

public class Consumer1 {
    readonly ISomeSingleton _mySingleton;
    public Consumer1(ISomeSingleton mySingleton) {_mySingleton = mySingleton;}
}

public interface ISomeSingleton{//All your methods you ned.}

public class SomeSingleton : ISomeSingleton
{
    private static SomeSingleton instance;

    public SomeSingleton() // constructor is now public
    {
    }

    public static SomeSingleton Instance // todo remove this when all consumers follow inversino of control pattern.
    {
        get
        {
            if (instance == null)
            {
                instance = new SomeSingleton();
            }

        return instance;
        }
    } 
}

消費者がSomeSingletonを直接呼び出さない場合は、それを削除できます。これにより、自分のペースで変更を加えることができます。

これで、SomeSingletonをインスタンス化する方法を理解する必要があります。これを手動で行うか、IOCコンテナを使い始めることができます。

テストでは、ISomeSingletonの異なる実装を作成できます。

0