Разница между этими двумя реализациями Singleton - PullRequest
3 голосов
/ 04 февраля 2012

Я учусь, как реализовать некоторые базовые шаблоны проектирования.Изучая паттерн Singleton, я заметил, что в Интернете есть две общие реализации:

// Possibly from: http://www.yoda.arachsys.com/csharp/singleton.html
// I cannot remember exact source, sorry :(

public sealed class Singleton
{
    // Static members are 'eagerly initialized', that is,
    // immediately when class is loaded for the first time.
    // .NET guarantees thread safety for static initialization
    private static readonly Singleton instance = new Singleton();

    // Private constructor prevents instantiation from other classes
    private Singleton() { }

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

    // Get the instance of the singleton
    public static Singleton getInstance()
    {
            return instance;
    }

}

и:

public class Singleton
{
  // Static, VOLATILE variable to store single instance
  private static volatile Singleton m_instance;

  // Static synchronization root object, for locking
  private static object m_syncRoot = new object();

  // Property to retrieve the only instance of the Singleton
  public static Singleton Instance
   {
      get
      {
          // Check that the instance is null
          if (m_instance == null)
          {
              // Lock the object
              lock (m_syncRoot)
              {
                  // Check to make sure its null
                  if (m_instance == null)
                  {
                      m_instance = new Singleton();
                  }
              }
          }

          // Return the non-null instance of Singleton
          return m_instance;
      }
  }
} 
  1. В каком сценарии вы бы предпочли иметь охотноinitialized vs lazy initialized?
  2. Является ли комментарий в первом примере правильным, говоря, что инициализация является поточно-ориентированной?(Я знаю, что это говорит, но это интернет ...)

Ответы [ 6 ]

3 голосов
/ 04 февраля 2012

Я бы определенно пошел с вашей первой реализацией ...

вторая мне кажется сомнительной ... если вам нужна / нужна ленивая реализация, вы можете использовать Lazy<T> для этого - так как это частьфреймворка он чувствует себя намного удобнее ..

Кстати: есть еще больше способов реализовать шаблон Singleton ... вот отличная статья .

2 голосов
/ 04 февраля 2012

Первый безопасен и ленив.

static constructor s гарантированно будет выполняться только один раз и непосредственно перед первым доступом к Instrance. Если есть статический конструктор (даже если он пуст), то инициализация статического поля гарантированно будет выполняться непосредственно перед статическим конструктором. Если статического конструктора нет, инициализация поля может произойти раньше.


Второй - ленивый, но я не уверен, действителен ли шаблон двойной блокировки, как этот. Я подозреваю, что он сломан, по крайней мере, в модели памяти ECMA.


Лично я бы избегал любого Class.Instance синглтона в пользу синглетонов IoC в большинстве ситуаций.

2 голосов
/ 04 февраля 2012

Я не уверен, но похоже, что вы получили эти примеры отсюда: http://www.yoda.arachsys.com/csharp/singleton.html

Если нет, прочитайте его. Есть две мысли о двух версиях. Если вы спросите меня лично: я бы выбрал второе решение, если бы мне нужно было знать, инициализирован ли синглтон или нет.

Если вам не нужно иметь дело с многопоточностью, я бы использовал еще более простой подход (см. Примеры «Плохой код» в ссылочной ссылке).

1 голос
/ 04 февраля 2012

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

1 голос
/ 04 февраля 2012

1) это полностью дизайнерский выбор. Инициализация инициализации или инициализация при необходимости.

2) Да, это потокобезопасный, поскольку CLR гарантирует инициализацию однопоточного объекта. (статический и экземпляр)

EDIT

лично, в первом примере я делаю поле Экземпляр общедоступным и не обращаюсь к получателю. Интересно узнать, есть ли какая-либо причина, что это плохая идея?

0 голосов
/ 28 февраля 2012

Обе реализации хороши, так что это зависит от того, что вам нужно.

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

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