ленивая инициализация синглетонов - PullRequest
3 голосов
/ 13 ноября 2009

Читая статью Джона Скита о синглетонах в C # Я начал задаваться вопросом, зачем нам сначала нужна ленивая инициализация. Кажется, четвертого подхода из статьи должно быть достаточно, вот он для справочных целей:

public sealed class Singleton
{
    static readonly Singleton instance=new Singleton();

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

    Singleton()
    {
    }

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

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

Так могут ли люди просветить меня, почему ленивая инициализация такая горячая вещь?

Ответы [ 4 ]

10 голосов
/ 13 ноября 2009

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

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

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

4 голосов
/ 13 ноября 2009

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

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

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

1 голос
/ 13 ноября 2009

Я не уверен, что это относится и к C #, но я отвечу за C ++:

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

Конкретный пример: допустим, у меня есть класс Log, который я решил реализовать как Singleton. Давайте также предположим, что у меня есть метод с именем LoadDB, который по какой-то причине является статическим, вызываемым в начале программы. Предполагая, что LoadDB решит, что ему нужно что-то записать, он вызовет Singleton. Но так как порядок статической инициализации не определен, возможно, он делает что-то, что является ошибкой.

Синглтон исправляет это, поскольку после вызова GetInstance (), независимо от того, где вы находитесь в процессе инициализации, объект гарантированно существует.

Опять же, я не знаю, относится ли это к делу, но, по крайней мере, это история (насколько я помню).

0 голосов
/ 01 сентября 2010

С точки зрения Java DI ленивая инициализация хороша, всегда есть (скажем, spring) bean-компоненты в другом API, которые вы, возможно, не захотите использовать, например, загруженный одноэлементный кеш (то, что доступно всем, кто использует кеш) вам может и не понадобиться, хотя в вашем же коде это может называться зависимостью. Какой смысл загружать ресурсы синглтона?

Выбор реализации отложенной инициализации сложен, если весной вы выберете lazy-init = "true" (spring с нетерпением создает экземпляры синглетонов), метод init-method / destroy, @PostConstruct, InitializingBean - afterPropertiesSet () или вернуть тот же экземпляр весны в методе getInstance ()?

Выбор - это компромисс между проверяемостью и возможностью повторного использования вне пружинного контейнера.

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