Мне нужно сохранить кучу переменных, к которым нужно получить доступ во всем мире, и мне интересно, применим ли одноэлементный шаблон. Из примеров, которые я видел, одноэлементный шаблон - это просто статический класс, который нельзя унаследовать. Но примеры, которые я видел, слишком сложны для моих нужд. Какой был бы самый простой одноэлементный класс? Могу ли я просто создать статический, закрытый класс с некоторыми переменными внутри?
Шаблон Singleton для С#
Ответ 1
Как правило, singleton не является статическим классом - singleton предоставит вам один экземпляр класса.
Я не знаю, какие примеры вы видели, но обычно singleton pattern может быть очень простым в С#:
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
static Singleton() {} // Make sure it truly lazy
private Singleton() {} // Prevent instantiation outside
public static Singleton Instance { get { return instance; } }
}
Это не сложно.
Преимущество singleton над статическими элементами заключается в том, что класс может реализовывать интерфейсы и т.д. Иногда это полезно, но в других случаях статические члены действительно будут делать то же самое. Кроме того, обычно легче перемещаться из одноэлементного режима в неэлементный элемент позже, например. передавая в singleton как "конфигурационный" объект в классы зависимостей, а не те классы зависимостей, которые создают прямые статические вызовы.
Лично я стараюсь избегать использования синглетов, где это возможно, - они делают тестирование сложнее, кроме всего прочего. Иногда они могут быть полезны.
Ответ 2
Существует несколько шаблонов, которые могут вам пригодиться, один из них один из худших.
Реестр
struct Data {
public String ProgramName;
public String Parameters;
}
class FooRegistry {
private static Dictionary<String, Data> registry = new Dictionary<String, Data>();
public static void Register(String key, Data data) {
FooRegistry.registry[key] = data;
}
public static void Get(String key) {
// Omitted: Check if key exists
return FooRegistry.registry[key];
}
}
Преимущества
- Легко переключиться на Mock Object для автоматического тестирования
- Вы все еще можете хранить несколько экземпляров, но при необходимости у вас есть только один экземпляр.
Недостатки
- Чуть медленнее, чем Singleton или глобальная переменная
Статический класс
class GlobalStuff {
public static String ProgramName {get;set;}
public static String Parameters {get;set;}
private GlobalStuff() {}
}
Преимущества
- Простой
- Fast
Недостатки
- Жестко переключаться динамически, то есть Mock Object
- Трудно переключиться на другой тип объекта, если изменения требований
Простой синглтон
class DataSingleton {
private static DataSingleton instance = null;
private DataSingleton() {]
public static DataSingleton Instance {
get {
if (DataSingleton.instance == null) DataSingleton.instance = new DataSingleton();
return DataSingleton;
}
}
}
Преимущества
- Нет действительно
Недостатки
- Сложно создать потокобезопасный синглтон, приведенная выше версия будет терпеть неудачу, если несколько экземпляров обращаются к экземпляру.
- Трудно переключиться на макет объекта
Лично мне нравится шаблон реестра, но YMMV.
Вы должны взглянуть на Injection Dependency, как обычно считается лучшей практикой, но это слишком большая тема, чтобы объяснить здесь.
Ответ 3
Синглтон - это не просто статический класс, который нельзя унаследовать. Это обычный класс, который может быть создан только один раз, причем все, кто использует этот единственный экземпляр (и делает его потокобезопасным, еще больше работают).
Типичный .NET-код для Singleton выглядит примерно так: Это быстрый пример, а не лучший вариант реализации или потокобезопасный код:
public sealed class Singleton
{
Singleton _instance = null;
public Singleton Instance
{
get
{
if(_instance == null)
_instance = new Singleton();
return _instance;
}
}
// Default private constructor so only we can instanctiate
private Singleton() { }
// Default private static constructor
private static Singleton() { }
}
Если вы собираетесь идти по пути, о котором вы думаете, статический герметичный класс будет работать нормально.
Ответ 4
Использование инициализаторов автоисточников С# 6.
public sealed class Singleton
{
private Singleton() { }
public static Singleton Instance { get; } = new Singleton();
}
Короткий и чистый - я буду рад услышать минусы.
Ответ 5
Итак, насколько мне известно, это самая краткая и простая реализация шаблона Singleton в С#.
http://blueonionsoftware.com/blog.aspx?p=c6e72c38-2839-4696-990a-3fbf9b2b0ba4
Я бы, однако, предположил, что синглтоны - действительно уродливые шаблоны... Я считаю их анти-шаблонами.
http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx
Для меня я предпочитаю иметь что-то вроде репозитория, реализующего IRepository. Ваш класс может объявить зависимость от IRepository в конструкторе и может быть передан с использованием Injection Dependency или одного из следующих методов:
Ответ 6
Используйте свои языковые функции. В основном простая реализация с поточной безопасностью:
public sealed class Singleton
{
private static readonly Singleton _instance;
private Singleton() { }
static Singleton()
{
_instance = new Singleton();
}
public static Singleton Instance
{
get { return _instance; }
}
}