Статический Vs. Вопрос Singleton обсуждался много раз в SO.
Тем не менее, все ответы указывали на многие преимущества синглтона.
Мой вопрос: каковы преимущества статического класса над одноэлементным?
Почему бы просто не выбрать один раз каждый раз?
Зачем выбирать статический класс по сравнению с одноэлементной реализацией?
Ответ 1
Статический класс - это технический инструмент в вашей коробке - в основном языковая функция.
Синглтон - это архитектурная концепция.
Вы можете использовать статический класс в качестве средства реализации концепции singleton. Или вы можете использовать другой подход.
С статическими классами в С# есть две потенциальные опасности, если вы не будете осторожны.
- Запрошенные ресурсы не будут освобождены до конца срока службы
- Значения статических переменных совместно используются в приложении. Особенно плохо для приложений ASP.NET, потому что эти значения будут затем разделяться между всеми пользователями сайта, находящегося в определенном домене приложений.
Ответ 2
От MSDN
Статические классы и члены класса используются для создания данных и функций к которым можно получить доступ, не создавая экземпляр класса. статический члены класса могут использоваться для разделения данных и поведения, которые независимо от любого идентификатора объекта: данные и функции не независимо от того, что происходит с объектом. Статические классы могут быть используется, когда в классе отсутствуют данные или поведение, зависящее от идентификатор объекта.
Ключевым моментом является то, что статические классы do not require an instance reference
. Также обратите внимание, что статические классы специально включены языком и компилятором.
Одиночные классы - это только классы, закодированные пользователем, реализующие шаблон дизайна Singleton. Цель Singleton - restrict instantiation of an class to a single instance
.
Если вы закодировали каждый статический класс как одноэлементный, вам нужно было бы создавать экземпляр класса каждый раз, когда вы его использовали.
то есть.
Console.WriteLine('Hello World');
станет
Console c = Console.getInstance();
c.WriteLine('Hello World');
Ответ 3
Я бы сказал, что они оба (вообще) плохие решения. Существует несколько вариантов использования статических классов, прежде всего простых служебных (на ум приходят методы расширения в С# 3.0). Однако с любой степенью сложности проблемы с тестируемостью начинают возникать.
Скажем, класс A зависит от статического класса B. Вы хотите изолировать класс A. Это тяжело.
Итак, вы идете с Singleton. У вас такая же проблема - класс A зависит от singleton B. Вы не можете тестировать класс A в изоляции.
Если класс B имеет другие зависимости (например, попадание в базу данных) или изменен (другие классы могут изменять свое глобальное состояние), проблема усугубляется.
IoC (Inversion of Control) - это одно из решений этой проблемы; они позволяют вам определять Обычные старые классы как имеющие долгую жизнь. В сочетании с насмешливой библиотекой они могут сделать ваш код очень надежным.
Ответ 4
Статические классы намного проще реализовать - я видел много попыток в потокобезопасных синглонах на С#, в которых используются схемы наивной блокировки вместо зависимости от гарантированной однократной инициализации статических полей (необязательно внутри вложенного класса для задержки создания экземпляра).
Кроме того, я думаю, что синглтоны великолепны, если вам нужно передать ссылку на объект, который реализует определенный интерфейс, когда эта "реализация" должна быть singleton, то, что вы не можете делать со статическими классами.
Ответ 5
Одно из соображений, о которых я не вижу, заключается в том, что предпочтение решения, использующего экземпляр класса (singletons или их эквивалент DI), позволяет вам предоставить класс, на котором другие пользователи вашего кода могут определять методы расширения - поскольку методы расширения работают только с нестационарными классами как параметр this
. Другими словами, если у вас есть строка, например:
GlobalSettings.SomeMethod();
Тогда синтаксически единственное, к чему можно обратиться через GlobalSettings
, - это члены, которые вы предоставляете. Напротив, если GlobalSettings
является экземпляром (singleton или иначе), то потребители могут добавлять свои собственные расширения к GlobalSettings
, чтобы они не могли сделать иначе:
application.GlobalSettings.CustomSomethingOrOther();
или
GlobalSettings.Instance.CustomSomethingOrOther();