2

所以看起来惰性实例化被广泛使用并且每个人都知道惰性实例化的优点。

这就引出了一个问题:我们应该懒惰地实例化每个对象吗?

我严重怀疑。

那么问题来了,惰性实例化的缺点是什么?

取自(Apple Sample LocateMe)的样本:

- (NSDateFormatter *)dateFormatter {
    if (dateFormatter == nil) {
        dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
        [dateFormatter setTimeStyle:NSDateFormatterLongStyle];
    }
    return dateFormatter;
}

这将为我们提供仅在需要时初始化此对象的优势。

顺便说一句,上面的示例取自 Apple,似乎他们只是懒惰地实例化“只读”对象。

4

1 回答 1

3

好的,我想我会以答案的形式改写我的回复(广告你现在有太多评论)......

在您给出的示例中,多次使用同一个对象实例是安全的,因为它的内部状态不受影响。也就是说,它提供服务并且不会在调用之间保持状态。

作为一般规则,惰性实例化仅与单例或通过工厂提供的那些实例真正相关。例如,就像在您的示例中一样,实例在“服务”或应用程序的持续时间内存在 - 例如资源处理。通常,您通常只想在需要时创建一个新的对象实例。

延迟初始化的优点/缺点是:

  • 您只需要初始化一个对象一次,一个实例就足以满足所有服务调用。通话之间不会保持状态。这里的好处是加载对象可能很耗时,因此您可以避免启动成本,或者在单例上下文中,您可以避免实例化多个昂贵的对象。这也适用于内存占用——一个实例,而不是多个实例。
  • 但是,如果您懒惰地初始化一个对象,则在运行时会产生成本,因为您实际上已经延迟了它的构造。所以,在运行时,当用户在等待时,你去创建一个昂贵的对象。不理想,所以你应该避免这种情况——如果它又是一个长期服务的对象。
  • 在您给出的示例中,还有一个对记忆负责的问题。客户端代码显然负责释放此实例。如果它是一个长期服务对象,他们在哪里做呢?好吧,您可能需要观察 NSApp 的 applicationWillTerminate 委托。
  • 如果一个实例维护在实例上的方法调用之间设置的状态,那么这种模式就不能工作。调用之间的实例状态可能不一致(可能已更改)。

另请注意,这是一种实例方法,如果实例 var 为空,则设置其值...这意味着,在这种情况下,每个封闭类实例(定义此方法的类)仍然有一个实例。在这种情况下,您的封闭实例负责清理。真的,我认为这是为了代码的清晰,而不是内存管理。或者,封闭类可能是长期存在的,它可以节省重新创建格式化程序(也许重新创建比重置更昂贵)。

如果想到其他任何内容,将进行编辑。希望能帮助到你。

于 2013-04-23T11:02:30.743 回答