В чем разница патерна Singleton и модификатора static в C#
Насколько я правильно понял static хранит состояние всего класса. С ним же можно создавать классы и методы. Тогда вопрос зачем нужен Singleton и в каких задачах его используют?
Ответы (1 шт):
В очень простом случае, синглтон - это по какой то причине [нужной причине] - единственный экземпляр "чего то".
Например, у вас есть класс окна, и он должен быть один, потому что вы так задумали. Но никто не запрещает в коде/кодом создать ещё несколько таких же окон, и запустить их. Тогда будет много экземпляров окон, и что делать? Некоторые экземпляры "чего то" - единственные, а синглтон обеспечивает в некотором смысле "защиту" от повторного создания экземпляра, например второго-третьего окна. Запрещает/противодействует созданию нескольких экземпляров "чего то".
Статик здесь совершенно ни при чём. Статические переменные, методы и классы - это детали реализации. Например общепринятых [или не очень] паттернов программирования.
В синглтонах [обычно] действительно объявляют тот самый единственный экземпляр - статическим. А почему? Если не вдаваться в подробности, то всякое статическое в тех же классах - поля/методы инициализируются и исполняются прежде всего. Грубо говоря всякое статическое будет исполнено, а уже затем - не статическое.
Тогда и есть смысл использовать синглтон, как единственный экземпляр - как статический, и при первом обращении к классу исполнится статическая часть класса, т.е. исполнится синглтон. Он же будет доступен по статическим полям/методам. Но это детали реализации.
public class Window
{
// Это статическое поле, при первом обращении
// к этому классу [на самом деле типу] -
// это поле исполнится прежде всего.
// Переменной Singleton будет назначен
// новосозданный экземпляр объекта Window.
public static readonly Window Singleton = new Window();
// Конструктор не запрещает создавать ещё
// экземпляры этого объекта.
public Window() // [1 вариант]
{
}
// Можно закрыть конструктор как private
// тогда внешний код не сможет создать экземпляр
// объекта Window, извне.
private Window() // [2 вариант]
{
}
}
public static class Program
{
public static void Main()
{
// Обращаемся к статическому полю
// класса окошка, а окошко создано
// самим классом Window.
Window windowOne = Window.Singleton;
// Можно создать ещё окошко, но если
// конструктор публичный, а если
// конструктор закрыт, то второе-третье
// окошко создать нельзя.
// Если конструктор public, создаём второе окно.
Window windowTwo = new Window();
// Если конструктор private, ошибка компиляции
// Закрытый конструктор не позволяет
// создавать окна ещё и ещё.
Window windowThree = new Window(); // Compile error
}
}
Статические классы, поля, методы - это детали ООП, способ организации кода, а синглтон - это логическая абстрактная единственность. Можно собрать синглтон иначе, например [почти] без статических штуковин.
public class Window
{
// Это статическое поле, при первом обращении
// к этому классу [на самом деле типу] -
// это поле исполнится прежде всего.
private static readonly bool _isCreated = false;
// Конструктор не запрещает создавать ещё
// экземпляры этого объекта, но флаг запрещает
// создавать более чем одно окно,
// и проверка этого флага _isCreated.
public Window()
{
// Проверяем флаг, изначально флаг=false
if (_isCreated)
throw new System.Exception("Окно уже создано.");
// Ставим флаг в true, последующие попытки
// создать окно будут выкидывать ошибку.
_isCreated = true;
}
}
public static class Program
{
public static void Main()
{
// Создаём окошко.
Window windowOne = new Window();
// Можно создать ещё окошко, но внутренний
// флаг конструктора окна проверяет единственность
// и будет выкинута ошибка, второе окно не получится.
Window windowTwo = new Window(); // Runtime error
}
}
Способов синглтонов превеликое количество, это детали реализации, а реализации разные, потому что нужны разные реализации. И единственных паттернов - не существует. Паттерны выбирают осмысленно, в тех или иных случаях подбирают паттерны или кодируют что то своё.
А самый простейший синглтон не требующий ничего от кода - это документация. И такое тоже практикуется. Нет кода - нет проблем. Самый хороший код - это такой код, которого нет.
public class Window
{
/// <summary>Это синглтон, создавайте один экземпляр этого класса.</summary>
public Window()
{
}
}
public static class Program
{
public static void Main()
{
// Создаём окошко.
Window windowOne = new Window();
// Можно создать ещё окошко, но если читаете
// документацию, то второе окошко не создадите,
// создание второго окна запрещает документация.
Window windowTwo = new Window(); // Documentation error
}
}