Каковы реальные применения синглтона? - PullRequest
15 голосов
/ 09 апреля 2009

Дублирование

На шаблонах проектирования: когда следует использовать синглтон?

class Singleton
{
    private static Singleton instance;

    private Singleton() {}

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
                instance = new Singleton();

            return instance;
        }
    }
}

Ответы [ 10 ]

16 голосов
/ 09 апреля 2009

Simple. Что делает синглтон?

  • Предоставляет глобальный доступ к экземпляру объекта, а
  • Это гарантирует, что никогда не может быть создано более одного экземпляра этого типа.

Таким образом, вы используете синглтон, когда вам нужно оба этих вещей.

И это редко. Глобалы вообще говоря, плохо. Мы стараемся избегать их, когда это возможно. И построение вашего приложения на предположении, что «если существует более одного экземпляра, это ошибка», опасно, потому что вы обычно обнаруживаете, что это предположение не выполняется. Возможно, вы хотите иметь возможность создавать несколько экземпляров локально для целей кэширования. Возможно, вам требуется более одной базы данных, более одного журнала или, возможно, производительность потоков требует, чтобы вы предоставили каждому потоку свой экземпляр.

В любом случае вам не нужно применять предположение «может существовать только один экземпляр». Если вам нужен только один экземпляр, просто создайте только один экземпляр. Но оставьте конструктор публично видимым, чтобы можно было создать больше экземпляров , если это окажется необходимым .

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

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

Единственное применение синглетонов в реальном мире, которое я когда-либо видел, было «архитектор прочитал книгу GoF и решил повсюду втирать шаблоны проектирования», или «какой-то программист, застрявший в 80-х, не доволен вся эта «объектно-ориентированная» вещь, и она требует процедурного кодирования, что означает хранение данных в виде глобалов. А синглтоны звучат как «ООП» способ создания глобалов, не крича на ».

Ключевым моментом является то, что синглтон сочетает в себе две, очень разные, и очень редко необходимые обязанности. Как правило, вы хотите самое большее один из них в любом данном объекте.

8 голосов
/ 10 мая 2011

В моем проекте мы создали компонент регистратора, который используется для входа в приложение к различным источникам (например, текстовый файл, XML и база данных на основе конфигураций). Таким образом, существует менеджер журналов, который создает единственный экземпляр класса регистратора в приложении для регистрации сообщений, ошибок и т. Д.

7 голосов
/ 10 апреля 2009

Джон Скит, THE_SKEET , написал отличную статью, в которой приводятся примеры различных способов правильной реализации (потокобезопасного, ленивого, производительного) шаблона Singleton.

Перейти читать здесь .


По многочисленным просьбам (er ... downvote) я воспроизводю версию Skeet:

public sealed class Singleton
{
    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

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

3 голосов
/ 09 апреля 2009

Хороший пример того, где я использовал Singleton, - это приложение, которое должно вызывать компонент веб-службы из нескольких мест внутри приложения. Мне нужно было поддерживать состояние, инициализировать некоторые поля и поддерживать очередь вызовов и обратных вызовов, чтобы я не мог просто делать статические вызовы. Но я хотел, чтобы во всем приложении использовался только один экземпляр. Я реализовал этот «сервисный» класс как синглтон, чтобы я мог вызывать его во всем приложении в ответ на множество разных событий, но все они обрабатывались в одном месте.

По моему опыту, я использовал синглтоны, где объект собирался использовать много раз в течение жизни приложения, требовал инициализации и / или занимал много памяти. В основном, когда имеется только один экземпляр класса, в котором потенциально может быть много экземпляров, и это будет дорогостоящим.

1 голос
/ 09 апреля 2009

Вы должны использовать Singleton, когда должен быть только один экземпляр объекта. Однако у Миско Хевери есть некоторые мысли о том, почему синглтоны плохие!

1 голос
/ 09 апреля 2009

Обратите внимание, что этот код не является потокобезопасным:

get   
{
   if (instance == null)   
      instance = new Singleton();   
    return instance;   
}   

Один поток может войти в функцию, пройти тест на нулевое значение и затем быть приостановлен. Затем можно запустить второй поток и пройти нулевой тест. С этого момента оба потока в какой-то момент создадут свою собственную копию объекта sungleton, только один из которых будет использован.

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

1 голос
/ 09 апреля 2009

Если ваш вопрос в заголовке:

Однажды я работал с COM-объектом, который мог иметь только один экземпляр на сервер. Мы представили его всему приложению ASP.NET через синглтон.

0 голосов
/ 11 февраля 2014

Это не синглтон, так как синглтон обеспечивает безопасность потока с ключевыми словами только для чтения.

Например,

public sealed class Singleton
{
    // private static Singleton instance; (instead of this, it should be like this, see below)
    private static readonly Singleton instance = new Singleton();

    static Singleton(){}

    private Singleton() {}

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
                instance = new Singleton();
            return instance;
        }
    }
}

Используя это, он обеспечит безопасность протектора и правильный рисунок синглтона (то есть, чем он отличается от статического класса). Ваш код для синглтона не был потокобезопасным.

Подробнее о синглтоне смотрите по ссылкам:

0 голосов
/ 09 апреля 2009

Один из способов, которыми я использовал синглтон, - реализовать объект «главный контроллер» для приложения. Это было немного похоже на объект Application, который вы получаете с VBA.

Этот объект выполнял различные задачи запуска и завершения работы. Он также предоставил доступ к настройкам и службам всего приложения. Это, в частности, значения параметров командной строки и службы ведения журнала.

0 голосов
/ 09 апреля 2009

Шаблон синглтона может оказаться полезным, если у вас есть ресурс, который стоит много времени для инициализации, и который вы используете несколько раз, например контекст объекта, когда вы используете ORM или соединение какой-то.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...