Являются ли неизменяемые / не имеющие состояния синглтоны плохими?

12

В последнее время произошла какая-то революция против синглетонов, но что с ними не так, если они не имеют гражданства?

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

m3th0dman
источник
1
Нет. Синглтоны в принципе неплохие, они просто чрезмерно используются.
Барт ван Инген Шенау
3
что вы имеете в виду в последнее время?
Manoj R
5
@Joachim Sauer: зачем вам нужно заменить; если он не имеет состояния, вы можете проверить его напрямую.
m3th0dman
1
Если у вас есть одноэлементный файл без сохранения состояния, то у вас есть статический класс полезности, который имеет тенденцию превращаться в анти-паттерн God Class. Обычно вы можете использовать статические методы вместо этого в контексте, в котором они используются (или даже лучше: использовать методы расширения в C #).
Спойк
1
Возможный дубликат Синглтона без какого-либо состояния
Caleth

Ответы:

12
  > Are immutable/stateless singletons bad?
  • Нет, если они не зависят от других внешних систем.
    • Пример: Stringutility, которая экранирует html внутри строки.
    • Причина: в юнит-тестах нет необходимости заменять это на макет / симулятор.
  • Да, если ваш неизменный / не имеющий состояния синглтон зависит от других внешних систем / сервисов и если вы хотите провести юнит-тестирование (тестирование в изоляции)
    • Пример: сервис, который зависит от внешнего налогового калькулятора-веб-сервиса.
    • Причина: для проведения юнит-тестов с помощью этой Услуги (изолированно) вам необходимо смоделировать / смоделировать внешние Системы / Услуги.

Для получения более подробной информации см. Архитектура лука


  • Singleton-ы могут сделать юнит-тестирование (изолированно) более трудным / невозможным и
  • скрытые зависимости / связь могут рассматриваться как проблема, как объясняет @yBee

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

k3b
источник
Вам все равно придется издеваться над этим внешним веб-сервисом, если вы хотите протестировать свой класс, даже если это не синглтон (без состояния).
m3th0dman
@ m3th0dman я согласен
k3b
10

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

Если у вас есть одноэлементный файл без сохранения состояния, почему бы не использовать класс, предлагающий только статические методы (или использовать статический класс)?

Вот несколько постов, касающихся глобальных переменных и синглетонов в целом.

Я не был бы таким строгим, как автор, но он показывает, что в большинстве случаев, когда вы думаете, что вам нужен синглтон, он вам на самом деле не нужен.

StampedeXV
источник
1
Почему бы не использовать класс со статическими методами? Наследование, например ...
m3th0dman
3
@ m3th0dman: не похоже на хорошее место для наследования.
Билли Онил
@BillyONeal Вы можете сказать, что что-то хорошее или плохое для наследования, если вы знаете модель предметной области, что должно моделироваться таким образом ...
m3th0dman
2
@ m3th0dman: Хм, нет. Я могу быть довольно позитивным, не зная ничего о модели предметной области. Наследование для полиморфного поведения. Но, как одиночка, у вас не будет полиморфного поведения.
Билли Онил
1
@ m3th0dman: потому что для получения одноэлементного объекта необходимо указать имя синглтона на сайте вызова. Это означает, что вы не используете полиморфное поведение. Это означает, что композиция гораздо более гибкая, чем наследование.
Билли ONEAL
7

Нет ничего, что неизменный синглтон без состояния может сделать, чего не может статический класс.

Нет просто никакой причины добавлять дополнительный уровень сложности, который создает -> Instance (), в то время как простой вызов статического метода будет более понятным, более консервативным с точки зрения ресурсов и, возможно, быстрее.

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

Научная фантастика
источник
Могу поспорить, что вы можете построить несколько случаев, когда синглтон имеет некоторые преимущества. Возможно, в зависимости от сценария и языка программирования (например, использование ленивой загрузки).
StampedeXV
1
@StampedeXV: Да, синглтон с определенным состоянием, конечно. Не имеющий статуса и неизменный - мне было бы очень любопытно услышать любые примеры, но я не затаил дыхание.
SF.
Хорошо, у вас есть смысл. Я немного обобщил ваш ответ. Для неизменного лица без гражданства я тоже не вижу никаких преимуществ.
StampedeXV
1
С классами, которые имеют только статические функции, вы не можете использовать наследование / полиморфизм, который является большим пределом ...
m3th0dman
1
Нет ничего, что неизменный синглтон без состояния может сделать, чего не может статический класс. ну, статические методы не могут реализовать интерфейс, который мог бы сделать синглтон
Michal M
3

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

С другой стороны, состояние без единого знака, если не злоупотреблять, может быть полезным и улучшить производительность. Рассмотрим пример:

interface Interface
{
    void Method();
}

class StatelessSingleton : Interface
{
    public static readonly StatelessSingleton Instance = new StatelessSingleton();
    private StatelessSingleton() { }

    public void Method() { }
}

class User
{
    public User(Interface i) { /* ... */ }
}

Здесь StatelessSingleton действует как реализация интерфейса по умолчанию и помещается в конструктор User. Нет жестко закодированных связей и скрытых зависимостей. Мы не можем использовать статический класс из-за базового интерфейса, но нет причин создавать более одного экземпляра по умолчанию. Вот почему синглтон без гражданства кажется подходящим выбором.

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

class Implementation : Interface
{
    private readonly Action _method;

    public Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

Это поражает производительность по отношению к StatelessSingleton, но представляет собой общую реализацию интерфейса. Аналогичное решение используется интерфейсом IProgress .

И опять же, зачем разрешать создавать более одной реализации поведения по умолчанию? Тем не менее мы можем объединить два:

class Implementation : Interface
{
    public readonly Implementation Default = new Implementation();

    private readonly Action _method;

    private Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

В заключение я считаю, что есть места (как показано по умолчанию), где синглтоны полезны. Основное определение Singleton гласит, что запрещено создавать более одного экземпляра класса. Это как ядерная энергия. Может производить энергию или бомбу. Это зависит от человека.

yBee
источник