Singleton или статический класс?

Помечено: , ,

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 3 мес., 2 нед. назад.

  • Автор
    Сообщения
  • #4052

    Всем известный шаблон проектирования Singleton, который запрещает создание более одного экземпляра класса, на первый взгляд, простой в реализации, а значит, как считают многие, говорить о нём особо нечего.

    А вот у меня почему-то много вопросов по нему возникает. Здесь я буду просто рассуждать вслух, а вы поправьте меня, если с чем-то не согласны. Вопрос, который хочу поднять в первую очередь – а в чём отличие шаблона Singleton от статического класса? И можно ли считать статический класс частным случаем Singleton-а? Вот с этим сейчас будем разбираться. Начнём с реализации.

    Шаблон Singleton предполагает такую реализацию класса, при которой можно создать только один его экземпляр. Как это реализуется в языке C#:

    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";  
       }
    }

    Мы реализуем класс, в котором переопределён конструктор без параметров, причём модификатор доступа назначаем ему private , чтобы нельзя было извне класса его вызвать. При этом у нас остаётся возможность создавать экземпляры класс прямо внутри самого класса. Итак, мы создаём приватную ссылку в качестве поля, создание экземпляра происходит в статическом конструкторе, который выполняется только один раз, но раньше экземплярного конструктора. Определяем открытое свойство для доступа к получившемуся экземпляру и добавляем модификатор static для поля и свойства.

    Для поля – чтобы можно было к нему обратиться в статическом конструкторе, для свойства – чтобы можно было к нему обращаться через имя класса, без привязки к созданию экземпляра.

    Итак, реализация простая. Если протестировать – мы можем создать любое количество ссылок на экземпляр Singleton-а, но при этом все они будут ссылаться на один и тот же объект в памяти.

    class Program
    {  
       static void Main(string[] args)   
       {  
          Singleton s1 = Singleton.Obj;  
          Console.WriteLine(s1.Data);   
       }
    }

    Хорошо, в плане программной реализации у нас всё получилось. Теперь посмотрим на статический класс.

    static class StaticData
    {  
       public static string Data { get; set; }    
       static StaticData()  
       {  
          Data = "I am a static class data";  
       }
    }

    Чтобы класс стал статическим, достаточно добавить к его определению модификатор static, и тогда создавать его экземпляры станет невозможно. Все члены такого класса тоже будут явно определяться как статические. Доступ к членам такого класса будет только через его имя, соответственно, только к открытым данным и методам. Экземпляров нет вообще и создать их нельзя, но данные могут быть предоставлены всем и везде, где это требуется.

    class Program
    {  
       static void Main(string[] args)  
       {    
          Console.WriteLine(StaticData.Data);  
       }
    }

    И тогда возникает вопрос – почему не использовать статические классы как Singleton и почему не считать их ещё одним способом реализации шаблона Singleton?

    На самом деле, ответ очень простой. Самое главное отличие лежит в самой формулировке Singleton – нам требуется ЭКЗЕМПЛЯР (хоть и только один). В случае статического класса экземпляров НЕТ (и не будет никогда).

    Идея статических классов вообще возникла из парадигмы языка C# об отсутствии глобальных данных, поскольку язык 100% объектно-ориентированный. Так вот помещение данных в статические классы, по сути, является способом это обойти. Он просто может объединять переменные и методы под единым идентификатором и давать возможности доступа к ним в любой точке кода любого класса.

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

    Для Singleton классов можно задавать любое количество базовых интерфейсов. Для статического класса невозможно задать интерфейс.

    В плане создания наследников они на равных: ни от Singleton -класса, ни от статического класса создавать дочерние типы нельзя. (Но Singleton может быть агрегирован, то есть ссылка на него может быть полем класса, которому нужна его функциональность. Ещё одно преимущества Singleton-класса в том, что его можно сериализовать, а соответственно, передавать по сети, хранить в файле и базе данных.

    Сохранить же состояние данных статического класса напрямую невозможно. Хотя, конечно, если меняются его данные часто, а их изменения нужно фиксировать, есть , например, шаблон, Memento. Но, как правило, статический класс как раз содержит данные не с тем, чтобы их постоянно менять, а чтобы предоставлять доступ на чтение для других классов. Также есть некоторый контроль над временем жизни объекта Singleton, поскольку и создавать его можно только по необходимости (отложенное инстанцирование), и удаление его из памяти скорее всего произойдёт раньше, чем очистка статических данных.

    Сам по себе Singleton – класс может использоваться в сочетании с другими шаблонами проектирования. Например, в Абстрактной фабрике, производимые продукты могут быть представлены экземплярами классов- Singleton-ов.

    Я думаю, перечисленных различий достаточно, чтобы можно было для себя решить, что использовать в конкретных ситуациях – Singleton или статический класс.

Для ответа в этой теме необходимо авторизоваться.