Альтернатива Singleton - это эквивалентно? - PullRequest
2 голосов
/ 26 февраля 2012

Быстрый вопрос -

Я знаю, что стандартный шаблон синглтона выглядит следующим образом:

Оригинал

public class Singleton1
{

    public static Singleton1 _Instance;
    public static Singleton1 Instance
    {
        get
        {
            if (_Instance == null)
            {
                _Instance = new Singleton1();
            }
            return _Instance;
        }
    }

    private Singleton1()
    {

    }
}

Но кажется, что этот код не нужен.Для меня вы можете сделать то же самое с помощью любого из следующих простых шаблонов проектирования:

Версия 2

public class Singleton2
{
    public static readonly Singleton2 Instance = new Singleton2();

    private Singleton2()
    {
    }
}

Версия 3

public class Singleton3
{
    static Singleton3()
    {
    }
}

Для меня этоПохоже, что версия 2 - лучший способ сделать это, потому что она позволяет передавать параметры (или нет), но при этом иметь конечное число экземпляров.Мое приложение довольно чувствительно к задержке / производительности - есть ли у какого-либо из этих шаблонов прирост производительности?

Может показаться, что при первом доступе к каждому из них будет больше времени, потому что объект создается.Кроме того, может показаться, что оригинал немного медленнее, потому что он должен проверять, является ли его вспомогательное поле нулевым, каждый раз, когда к нему обращается другой объект.

Спасибо заранее!

Ответы [ 5 ]

7 голосов
/ 26 февраля 2012
public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());

    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
}

Быстрый, чистый, поточно-ориентированный.

3 голосов
/ 26 февраля 2012

Одна проблема с синглетами, реализованными как статические экземпляры, заключается в том, что они затрудняют тестирование и макетирование.

Смотрите этот сценарий:

public void BusinessLogicMethod()
{
    var initialValue = MySingleton.Instance.GetInitialValue();
    var processedValue = initialValue + specialSomething + businessLogic;
    MySingleton.Instance.SaveProcessedValue(processedValue);
}

Теперь, допустим, я хочу написать юнит-тест для этого метода.В идеале я хочу написать тест, который определяет ввод и вывод и тестирует только бизнес-логику.Но со статическим синглтоном реализация метода привязана к реализации синглтона.Могу ли я легко установить InitialValue в начале теста, или это зависит от других факторов / доступа к БД / чего-либо еще?

Однако, если я использую нестатический синглтон в сочетании с некоторым внедрением зависимости или службойШаблон локатора, я могу построить свою функцию следующим образом:

public void BusinessLogicMethod()
{
    var singleton = ServiceLocator.Resolve<MySingleton>();
    var processedValue = singleton.InitialValue + specialSomething + businessLogic;
    singleton.SaveProcessedValue(processedValue);
}

, и мой тест может пойти так, используя смутный синтаксис Moq-подобного:

public void TestBusinessLogic()    
{
    MySingleton fakeSingleton = new Mock<MySingleton>();
    fakeSingleton.Setup(s => s.InitialValue).Returns(5);

    // Register the fake in the ServiceLocator
    ServiceLocator.Register<MySingleton>(fakeSingleton.Object);

    // Run
    MyBusinessMethod();

    // Assert        
    fakeSingleton.Verify (s => s.SaveProcessedValue()).Called(Exactly.Once);
} 

, не беспокоясь о РЕАЛЬНОМСинглтонная реализация.

1 голос
/ 26 февраля 2012

Singleton2 не совпадает с Singleton1, так как Instance не "ленивый" оценивается.В Singleton1 экземпляр создается только тогда, когда к нему обращаются, и с тех пор используется тот же самый.В SingleTon2 Экземпляр инициализируется с классом и перед тем, как к нему фактически обращаются.

0 голосов
/ 26 февраля 2012

Чтобы ответить на вопрос об эффективности, время, необходимое для проверки того, является ли закрытое поле пустым, незначительно.Поэтому я не буду беспокоиться о том, как это реализовано в отношении производительности здесь.

0 голосов
/ 26 февраля 2012

Моя любимая одноэлементная реализация: http://www.codeproject.com/Articles/14026/Generic-Singleton-Pattern-using-Reflection-in-C

Убедитесь, что ваш .ctor не является общедоступным, что является самой распространенной ошибкой, тогда его можно безопасно / полностью использовать повторно.

(мне нужно присмотреться к фильму Питера Кисс, который тоже выглядит красиво)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...