Какая конструкция предпочтительнее и почему при использовании шаблона синглтон-дизайна? - PullRequest
1 голос
/ 26 октября 2011

Помимо " что плохого в синглетах " :-), у меня есть веб-приложение ASP.NET, которое использует синглеты на уровне бизнес-логики, таким образом:

public class MyBusinessService
{
    private static MyBusinessService mInstance = null;

    public static MyBusinessService Instance
    {
        get { return mInstance; }
    }

    static MyBusinessService()
    {
        mInstance = new MyBusinessService();
    }
}

Мы используем их главным образом для зависимости в Model View Presenter архитектуре.

Они также могут использоваться в классах бизнес-логики одним из двух способов.Во-первых, следующим образом:

var myService = new MyBusinessService();
myService.DoSomething();
myService.DoSomethingElse();

Или его можно использовать следующим образом:

MyBusinessService.Instance.DoSomething();
MyBusinessService.Instance.DoSomethingElse();

Какая конструкция предпочтительнее и почему?Меня не интересует, является ли сам шаблон синглтона хорошим или плохим.

Обновление: Хорошо, этот вопрос кажется довольно популярным.Я думаю, это квази-синглтон.Худший из обоих миров!Я не очень заинтересован в рефакторинге шаблона / анти-шаблона / кода ада.Меня больше интересует понимание эффектов обоих описанных способов использования.

Наше представление (страница ASP.NET) выглядит следующим образом:

var presenter = new SomeViewPresenter(this, MyBusinessService.Instance);

, но в качестве альтернативы может быть реализовано как:

var presenter = new SomeViewPresenter(this, new MyBusinessService());

Я предпочитаю первое в этом случае.NB. Использование слова singleton и неправильное использование, приведенное выше, понятно, но как обстоят дела с кодом, каков результат двух оригинальных вариантов?

Ответы [ 6 ]

2 голосов
/ 26 октября 2011

Последний предпочтительнее, потому что первый не ведет себя как синглтон - вы создаете новый экземпляр без каких-либо средств защиты для остановки более одного существующего экземпляра.

Последний - код, который вы, скорее всего, вероятнов конечном итоге, если вы поставите этих охранников на место.Вам также не нужно постоянно использовать это свойство:

var service = MyBusinessService.Instance;
service.This();
service.That();

Я также смотрю на статику в ASP.NET с некоторым скептицизмом, и это от разработчика WinForms: -)

2 голосов
/ 26 октября 2011

Ваш класс не является одноэлементным без частного конструктора

Так что, если вы добавите закрытый конструктор

private MyBusinessService()
{
}

Тогда вы ограничены вашим вторым использованием, и это единственный класс

1 голос
/ 26 октября 2011

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

Ваша способность «обновлять» MyBusinessService побеждает единственную цель. Если вы хотите иметь возможность создавать новые экземпляры по своему усмотрению, просто сделайте это обычным экземпляром класса. Если вы хотите ограничиться одним экземпляром, то по определению у вас не должно быть доступа к конструктору по умолчанию.

Вот как ваш класс выглядел бы как настоящий синглтон:

public class MyBusinessService
{
    private static MyBusinessService mInstance = null;

    public static MyBusinessService Instance
    {
        get { return mInstance; }
    }

    static MyBusinessService()
    {
        mInstance = new MyBusinessService();
    }

    private MyBusinessService() {}
}

Добавление конструктора экземпляра по умолчанию, помеченного как private, означает, что var myService = new MyBusinessService(); не будет компилироваться вне области действия MyBusinessService (ограничивая его использование статическим конструктором).

Еще одна вещь; Если MyBusinessService может использоваться не во всех случаях или его создание дорого, вы можете подумать, что оно может быть ленивым. По умолчанию статические конструкторы запускаются при запуске; однако статические члены не оцениваются до тех пор, пока на них не будут сделаны первые ссылки. Таким образом, вы можете настроить свой класс следующим образом, и экземпляр MyBusinessService не будет создан, пока программа не узнает, что он понадобится:

public class MyBusinessService
{
    //the instantiation will not happen until the Instance property is called
    private static readonly MyBusinessService mInstance = new MyBusinessService();

    public static MyBusinessService Instance
    {
        get { return mInstance; }
    }

    private MyBusinessService() {}
}
1 голос
/ 26 октября 2011

Первый, возможно, предпочтительнее, так как он не синглтон.Поскольку вы хотите оставить в стороне аргументы о синглетах, второй вариант предпочтительнее, потому что это так.

0 голосов
/ 26 октября 2011

Из этих двух вариантов предпочтительным является второй, поскольку он ведет себя как настоящий синглтон.

Подробное руководство по реализации Singleton см. http://csharpindepth.com/Articles/General/Singleton.aspx.

Вы обнаружите, что следует учитывать несколько аспектов (например, производительность, ленивость, исключения, безопасность потоков и т. Д.).

0 голосов
/ 26 октября 2011

Два варианта выше довольно разные. Первая опция будет вызывать ctor по умолчанию, но вторая опция не будет. Это может или не может быть проблемой в зависимости от того, нужно ли вам инициализировать какие-либо элементы экземпляра.

Мои предпочтения - вариант № 2, если вам не нужен ctor на основе экземпляра. Это действительно зависит от того, как вы его используете.

...