#c_sharp #шаблоны_проектирования
Разбираюсь сейчас Singletone, нашел в сети несколько разных реализаций, но так и
не понял, как они работают. Синглтон - это паттерн, который гарантирует наличие только
одного экземпляра класса, а в примерах я немного не понимаю, как эта "гарантия" реализуется.
Первый пример
public sealed class MySingleton {
static MySingleton myInstance = null;
MySingleton()
{
}
public static MySingleton MyInstance
{
get
{
if (myInstance = = null)
{
myIinstance = new MySingleton();
}
return myInstance;
}
private set;
}
}
Второй пример:
class Singleton
{
static Singleton obj;
public static Singleton Obj { get { return obj; } }
public string Data { get; set; }
static Singleton()
{
obj = new Singleton();
}
private Singleton()
{
Data = "I am a singleton";
}
}
//вызов
{
static void Main(string[] args)
{
Singleton s1 = Singleton.Obj;
Console.WriteLine(s1.Data);
}
}
Собственно, можете объяснить чем эти два примера отличается друг от друга, и как
они гарантируют наличие одного экземпляра класса? Или они оба неправильны, и есть более
простая и понятная реализации паттерна на c#?
Ответы
Ответ 1
Гарантия реализуется за счет того, что класс Singleton не предоставляет никаких других способов получения экземпляра, кроме статического свойства - а свойство написано так, что двух разных экземпляров никогда не отдаст. Обратите внимание на приватный конструктор - для синглтонов это очень важно. Отличие между приведенными примерами в том, что первый вариант создает экземпляр по требованию - второй же создает свой экземпляр при инициализации класса. Вообще говоря, так как инициализация класса в .NET, в свою очередь, также происходит по требованию - различие тут не очень-то и велико. Еще если отличия в потокобезопасности - для статических конструкторов потокобезопасность гарантируется средой, а вот первый вариант синглтона может работать только в однопоточной среде. По поводу простых примеров - вот так синглтоны обычно пишу я: public class Foo { private Foo() { } public static readonly Foo INSTANCE = new Foo(); // ... } По сути, это второй вариант - но выглядит он куда проще. Тут просто создается неизменяемая статическая переменная, и ничего больше. PS Современные тенденции - избегать синглтонов; не следует делать синглтонами все подряд. Перед тем как некоторый класс сделать синглтоном, задумайтесь: а что страшного случится если кто-то (возможно, вы сами) создаст второй экземпляр этого класса? В большинстве случаев, ответ - "да ничего не случится". Если это так - не надо делать класс синглтоном.Ответ 2
Примеры синглтонов, которые используются в .NET Framework, можно посмотреть в исходниках .NET Framework Простая реализация синглтона: public class Data { public static readonly Data Instance = new Data(); private Data() { } } Если Data - это большой объект, и его надо создавать по-требованию, то можно использовать Lazypublic class Data { static readonly Data _Instance = new Lazy(() => new Data(), LazyThreadSafetyMode.PublicationOnly); public static Data Instance { get { return _Instance.Value; }} private Data() { } } Ответ 3
Простая реализация - использование Lazy. Как раз именно с Lazy задумываться над всеми этими многопоточными реализациями уже не приходится, работает из коробки. Код отсюда: public sealed class Singleton { private static readonly Lazy instanceHolder = new Lazy (() => new Singleton()); private Singleton() { ... } public static Singleton Instance { get { return instanceHolder.Value; } } } Я под синглтон использую обычно класс настроек программы. Ну т.е. у них есть метод Save и куча полей, которые мне нужны в рантайме. Если вдруг когда то мне захочется добавить профили настроек - достаточно расшить точку Instance, а не переписывать абсолютно все обращения к настройкам в коде, в этом преимущество. Разница со статик классами небольшая, но мне например в статик классах постоянно мешает то, что расшивать их обычно очень неудобно. Плюс, хранить два экземпляра статик класса в качестве двух профилей настроек уже не получится. Тогда как тупая сериализация инстанса - вполне рабочее решение.
Комментариев нет:
Отправить комментарий