Альтернатива синглтон-фабрике - PullRequest
0 голосов
/ 16 марта 2012

Я пишу обертку вокруг библиотеки классов, которую я не могу контролировать.В этой библиотеке есть класс (назовем его Target), который я хочу убедиться, что он создается только один раз, но сам по себе он не является одиночным.Я подумал об использовании шаблона Singleton-Factory следующим образом:

internal sealed class SingletonFactory
{
    private static readonly SingletonFactory manager = new SingletonFactory();

    private readonly Target target;

    private static SingletonFactory() { }

    private SingletonFactory()
    {
        target = new Target();
        target.Init("foo");
    }

    internal static SingletonFactory Instance
    {
        get { return manager; }
    }

    internal Target Target
    {
        get { return target; }
    }
}

Затем я могу сделать:

var targetInstance = SingletonFactory.Instance.Target;

Затем я подумал об упрощении этого, сделавФабрика полностью статична, как это:

internal static class StaticFactory
{
    private static readonly Target target;

    private static StaticFactory()
    {
        target = new Target();
        target.Init("foo");
    }

    internal static Target Target 
    {
        get { return target; }
    }
}

и доступ к целевому экземпляру становится:

var targetInstance StaticFactory.Target;

Я почти уверен, что StaticFactory является поточно-ориентированным и обеспечивает глобальный доступв один экземпляр целевого класса.Что-то не так с этим, о чем я не подумала?

Ответы [ 2 ]

1 голос
/ 16 марта 2012

Я не уверен, что ваш конструктор действительно потокобезопасен, поскольку технически он может быть доступен из разных потоков одновременно. Вы можете заблокировать private static readonly object Lock = new object(); для обеспечения безопасности потоков.

Если мы говорим о C # 4, вы также можете взглянуть на Lazy<T> здесь http://msdn.microsoft.com/de-de/library/ee792409.aspx. Он поддерживает потоковый безопасный режим создания LazyThreadSafetyMode, который позволяет найти компромисс между безопасностью и производительностью. .

Sidenote: В конце концов, отказ от использования статического класса может быть лучшим решением при проектировании, поскольку вы предотвращаете архитектурно-невидимую зависимость и получаете возможность менять реализации. Работа с абстрактными фабриками решает эту проблему (а также дает хороший опыт модульного тестирования).

1 голос
/ 16 марта 2012

То же самое, за исключением того, что у вас было ключевое слово private в статическом конструкторе, что запрещено.

internal static class StaticFactory
{
    public static Target Target = new Target();

    static StaticFactory()
    {
       Target.Init("foo");
    }
}

Вы можете стать фантазером и засунуть все это в Ленивого:

public static Lazy<Target> Target =
      new Lazy<Target>(() => { var t = new Target(); t.Init(""); return t; });

Вы также можете создать фасад, который даст вам ту же семантику, что и Target, но сохранит его как один экземпляр. Это также дает вам возможность поиграть с тем, где и когда вы инициализируете целевой объект.

public class TargetFacade
{
   private static Target _target = new Target();

   static StaticFactory()
   {
      _target.Init("foo");
   }

   //Wrap Target's methods here.
   public int Score { get { return _target.Score } }; 
}
...