Зачем выбирать статический класс вместо одноэлементной реализации? - PullRequest
30 голосов
/ 24 августа 2009

Статический Vs. Синглтонский вопрос уже много раз обсуждался в SO.
Однако во всех ответах указывалось на множество преимуществ синглтона.
Мой вопрос - в чем преимущества статического класса перед синглтоном? Почему бы просто не выбрать синглтон каждый раз?

Ответы [ 5 ]

40 голосов
/ 24 августа 2009

Статический класс - это технический инструмент в вашей коробке - в основном языковая функция.

Синглтон - это архитектурная концепция.

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

Со статическими классами в C # есть две потенциальные опасности, если вы не будете осторожны.

  • Запрошенные ресурсы не будут освобождены до конца срока службы приложения
  • Значения статических переменных совместно используются в приложении. Особенно плохо для приложений ASP.NET, потому что эти значения будут разделены между всеми пользователями сайта, находящимися в определенном домене приложения.
23 голосов
/ 24 августа 2009

С 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');
9 голосов
/ 24 августа 2009

Я бы сказал, что они оба (как правило) плохие решения. Существует несколько вариантов использования статических классов, в первую очередь простых служебных (на ум приходят методы расширения в C # 3.0). Однако при любой степени сложности проблемы с тестируемостью начинают возникать.

Скажем, класс A зависит от статического класса B. Вы хотите протестировать класс A изолированно. Это сложно.

Итак, вы идете с синглтоном. У вас та же проблема - класс A зависит от синглтона B. Вы не можете тестировать класс A изолированно.

Когда класс B имеет другие зависимости (например, попадание в базу данных) или изменчив (другие классы могут изменять его глобальное состояние), проблема усугубляется.

Контейнеры библиотеки

IoC ( Inversion of Control ) являются одним из решений этой проблемы; они позволяют определять простые классы как имеющие длительный срок службы. В сочетании с фиктивной библиотекой они могут сделать ваш код очень тестируемым.

6 голосов
/ 24 августа 2009

Статические классы гораздо проще реализовать - я видел много попыток поточно-ориентированных синглетонов в C #, которые используют наивные схемы блокировки вместо зависимости от гарантированной одноразовой инициализации статических полей во время выполнения (опционально внутри вложенного класса отложить инстанцию).

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

2 голосов
/ 24 февраля 2014

Одно соображение, о котором я не упомянул, заключается в том, что предпочтение решения с использованием экземпляра класса (синглтонов или их DI-эквивалента) позволяет вам предоставить класс, для которого другие пользователи вашего кода могут определять методы расширения - поскольку методы расширения работают только с нестатическими классами в качестве параметра this. Другими словами, если у вас есть строка вроде:

GlobalSettings.SomeMethod();

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

application.GlobalSettings.CustomSomethingOrOther();

или

GlobalSettings.Instance.CustomSomethingOrOther();
...