Синглтон-паттерн (решение Билла Пью) - PullRequest
29 голосов
/ 24 мая 2011

Я читаю вики о шаблоне синглтона, и я не уверен, что понимаю: https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom часть его правильно.

Итак, чтобы сделать это проще: Почему решение Билла Пью лучше, чем в примере выше?

Это потому, что статический класс не загружается виртуальной машиной до его фактического использования, или что-то в этом роде, поэтому мы не создаем объект до того, как обратимся к методу getInstance ()? Кроме того, этот метод потокобезопасен только для степени инициализации объекта?

Ответы [ 5 ]

30 голосов
/ 24 мая 2011

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

Как говорится в статье, метод мистера Пью более ленив, чем статическая переменная экземпляра, но на самом деле, если класс Singleton загружается, вы все равно будете вызывать метод getInstance.Так что, как упражнение по информатике, это полезно, но в реальном мире его преимущества спорны.

ps Меня не волнует пример мистера Блоха, так как использование перечисления означало бы сказать, что My Singleton IS-Перечисление, которое мне не подходит (особенно от того, кто справедливо говорит, что никогда не реализует интерфейс только для получения констант)

23 голосов
/ 24 мая 2011

JLS гарантирует, что класс загружается только при его первом использовании (что делает инициализацию синглтона ленивой), и что загрузка класса является поточно-ориентированной (что делает метод getInstance() потоком-безопасно)

Что касается того, почему потокобезопасен

Поскольку при первом вызове getInstance () JVM будет содержать класс-держатель.Если другой поток вызывает getInstance () одновременно, JVM не будет загружать класс держателя второй раз: он будет ждать, пока первый поток завершит загрузку класса, и в конце загрузки и инициализации класса держателя,оба потока увидят, что класс-держатель правильно инициализирован и, таким образом, содержит уникальный экземпляр singleton.

7 голосов
/ 24 мая 2011

Это потому, что статический класс не загружается виртуальной машиной до его фактического использования

Не просто статический класс, любой класс.Классы не загружаются, пока на них нет ссылок.См. JLS - 12.4.1 Когда происходит инициализация

или что-то в этом роде, поэтому мы не создаем объект, прежде чем обратимся к методу getInstance ()?

Точно.

Также является ли этот метод безопасным для потока только при условии инициализации объекта?

Передача ссылки является поточно-ориентированной, так что этот метод всегда потокобезопасен, а не только во время создания

1 голос
/ 24 мая 2011

Ключевая часть объяснения следующая:

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

Решение Билла Пога обеспечивает лень.

1 голос
/ 24 мая 2011

Это потому, что статический класс не загружается виртуальной машиной до его фактического использования, или что-то в этом роде, поэтому мы не создаем объект до того, как обратимся к методу getInstance ()?

Правильно.

Кроме того, этот поток методов безопасен только для степени инициализации объекта?

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

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