Статьи

C # — шаблон Singleton против статических классов

Проблема: Храните некоторые общие данные в одиночном или статическом классе о вашей программе в массиве объектов, который вы храните в классе. Он сохраняет состояние между использованиями и хранит некоторые кэши, и его нужно инициализировать только один раз и использовать во многих местах кода. Создание нового объекта каждый раз будет дорого.

Решение

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

Представляем шаблон Singleton

Наше идеальное решение называется шаблон синглтон-дизайна. Вот реализация синглтона, которую я буду использовать. Как вы знаете, синглтон — это объект с одним экземпляром. Это очень эффективно и очень изящно. У синглетонов есть статическое свойство, к которому вы должны получить доступ, чтобы получить ссылку на объект.

/// <summary>/// Sample singleton object./// </summary>public sealed class SiteStructure{    /// <summary>    /// Possible an expensive resource we need to only store in one place.    /// </summary>    object[] _data = new object[10];    /// <summary>    /// Allocate ourselves. We have a private constructor, so no one else can.    /// </summary>    static readonly SiteStructure _instance = new SiteStructure();    /// <summary>    /// Access SiteStructure.Instance to get the singleton object.    /// Then call methods on that instance.    /// </summary>    public static SiteStructure Instance    {        get { return _instance; }    }    /// <summary>    /// This is a private constructor, meaning no outsides have access.    /// </summary>    private SiteStructure()    {        // Initialize members, etc. here.    }}

Пример статического класса

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

/// <summary>/// Static class example. Pay heed to the static keywords./// </summary>static public class SiteStatic{    /// <summary>    /// The data must be a static member in this example.    /// </summary>    static object[] _data = new object[10];    /// <summary>    /// C# doesn't define when this constructor is run, but it will     /// be run right before it is used most likely.    /// </summary>    static SiteStatic()    {        // Initialize all of our static members.    }}

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

Преимущества синглтона

Синглтоны сохраняют традиционный подход к классам и не требуют, чтобы вы использовали везде ключевое слово static. Сначала они могут быть более сложными для реализации, но значительно упростят архитектуру вашей программы. В отличие от статических классов, мы можем использовать синглтоны в качестве параметров или объектов.

// We want to call a function with this structure as an object.// Get a reference from the Instance property on the singleton.{    SiteStructure site = SiteStructure.Instance;    OtherFunction(site); // Use singleton as parameter.}

Наследование интерфейса

В C # интерфейс — это контракт, и объекты, имеющие интерфейс, должны соответствовать всем требованиям этого интерфейса. Обычно требования к интерфейсу являются подмножеством рассматриваемого объекта. Вот как мы можем использовать синглтон с интерфейсом , который в примере называется ISiteInterface .

/// <summary>/// Stores signatures of various important methods related to the site./// </summary>public interface ISiteInterface{};/// <summary>/// Skeleton of the singleton that inherits the interface./// </summary>class SiteStructure : ISiteInterface{    // Implements all ISiteInterface methods.    // [omitted]}/// <summary>/// Here is an example class where we use a singleton with the interface./// </summary>class TestClass{    /// <summary>    /// Sample.    /// </summary>    public TestClass()    {        // Send singleton object to any function that can take its interface.        SiteStructure site = SiteStructure.Instance;        CustomMethod((ISiteInterface)site);    }    /// <summary>    /// Receives a singleton that adheres to the ISiteInterface interface.    /// </summary>    private void CustomMethod(ISiteInterface interfaceObject)    {        // Use the singleton by its interface.    }}

Теперь мы можем повторно использовать наш синглтон для любой реализации объектов, соответствующих интерфейсу. Может быть 1, 2 или 10. Нам не нужно ничего переписывать снова и снова. Мы храним состояние более условно, используем объекты по их интерфейсам и можем использовать традиционные методы объектно-ориентированного программирования .

Вывод

Здесь мы можем намного проще использовать код и управлять состоянием объекта . Это позволяет значительно улучшить совместное использование кода и значительно более чистое тело кода. С меньшим количеством кода ваши программы обычно будут иметь меньше ошибок и их будет легче поддерживать. Одна хорошая книга на эту тему называется C # Design Patterns и написана Джудит Бишоп.