繁体   English   中英

懒惰的单例初始化

[英]lazy initialization of singletons

在阅读Jon Skeet关于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;
        }
    }
}

在极少数情况下,在单例上有其他静态方法,延迟初始化可能有好处,但这不是一个好的设计。

那么人们可以告诉我为什么懒惰的初始化是如此热门的事情?

在那些可能根本不需要初始化的情况下,并且初始化成本很高(在CPU周期或资源方面),然后实现延迟初始化可以在不需要对象的情况下节省成本。 。

如果始终需要该对象,或者初始化相对便宜,那么延迟初始化器没有额外的好处。

在任何情况下,不正确地实现惰性初始化程序可以使单例非线程安全,因此如果您需要此模式,请小心正确执行。 Jon的文章有一个模式,(我认为这是最后一个),解决了这个问题。

如果您要使用该类型的唯一原因是引用该实例,则不需要在单例上进行延迟初始化。

但是,如果您在类型或类型本身上引用任何其他属性或方法,则将初始化单例。

当然,好的设计会为一种类型留下一个任务,所以这应该不是问题。 但是,如果将单例类设置为“复杂”,则延迟初始化可以帮助您避免由于过早初始化而导致的后果。

我不确定这也适用于C#,但我会回答C ++:

Singletons背后的一个想法是静态对象的初始化顺序是不确定的。 因此,如果您有一个试图使用另一个静态类的静态类,您可能会遇到麻烦。

一个具体的例子:假设我有一个Log类,我决定将其作为Singleton实现。 我们还假设我有一个名为LoadDB的方法,无论出于何种原因,它都是在程序开始时调用的静态。 假设LoadDB决定它需要记录某些内容,它将调用Singleton。 但由于静态初始化的顺序未定义,因此它可能正在做一些错误。

Singleton修复此问题,因为一旦调用GetInstance(),无论您在初始化过程中的哪个位置,都保证该对象存在。

同样,我不知道这是否相关,但至少这是它的历史(据我记得)。

从Java DI的角度来看,延迟初始化很好,在你可能不想使用的另一个API中总有(例如,spring)bean,例如,一个急切加载的单例缓存(与使用缓存的每个人共享的东西)可能虽然它可能在同一代码中被称为依赖项,但您并不需要它。 加载单身浪费资源的重点是什么?

懒惰的初始化实现选择很棘手,在春天,你会选择lazy-init =“true”(spring急切地实例化单例),init-method / destroy-method,@ PostConstruct,InitializingBean - afterPropertiesSet()方法或返回相同的弹簧getInstance()方法中的实例?

选择是可测试性与弹簧容器外的可重用性的权衡。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM