2016-03-08 3 views
2

Я смотрел исходный код мессенджера Telegrams, и я заметил, что их классы singleton используют локальные переменные в методах getInstance, как показано ниже. К примеру, на их Android GitHub repo, на классе NotificationsController.java они имеют следующее:Singleton - Лучший способ создать экземпляр класса

private static volatile NotificationsController Instance = null; 
public static NotificationsController getInstance() { 
    NotificationsController localInstance = Instance; 
    if (localInstance == null) { 
     synchronized (MessagesController.class) { 
      localInstance = Instance; 
      if (localInstance == null) { 
       Instance = localInstance = new NotificationsController(); 
      } 
     } 
    } 
    return localInstance; 
} 

Я не совсем уверен, что цель локальной переменной «localInstance» там. Может ли кто-нибудь объяснить, в чем заключается цель «localInstance» var? Не удалось ли добиться такого же результата, как в приведенном ниже коде?

private static volatile NotificationsController Instance = null; 
public static NotificationsController getInstance() { 
    if (Instance == null) { 
     synchronized (MessagesController.class) { 
      if (Instance == null) { 
       Instance = new NotificationsController(); 
      } 
     } 
    } 
    return Instance; 
} 
+1

В вашей версии, вы также отсутствует второй 'if' проверить внутри' synchronized' блока. Это означает, что конструктор можно вызвать дважды. – Thilo

+0

Просто выглядит как плохой код для меня. Для начала Singleton шаблон выше - это анти-шаблон http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons. Во-вторых, они синхронизируются с объектом класса другого класса, который может вызвать тупик, если какой-либо другой фрагмент кода решает взять блокировку этого объекта, в-третьих, точку, которую вы поднимаете. У GitHub только один основной вкладчик. Я бы не решался использовать эту библиотеку. – Samuel

ответ

1

Это сделано по соображениям безопасности.

Рассмотрите наиболее распространенный сценарий, в котором была инициализирована переменная. Код, записанный, будет считывать переменную volatile один раз и возвращать значение. Ваша версия будет читать его дважды. Поскольку волатильные чтения несут небольшую производительность, использование локальной переменной может быть быстрее.

Потому что в вашем случае лениво инициализированная переменная является статической, желательно использовать икону класса владельца. См. Пример this answer.

Смежные вопросы