我想要批评我用来创建对象的以下方法:
在界面文件中:
MyClass * _anObject;
...
@property (retain, nonatomic) MyClass * anObject;
在实施文件中:
@property anObject = _anObject
到目前为止,这么简单。现在让我们覆盖默认的getter:
(MyClass *) anObject {
if(_anObject == nil) {
self.anObject = [[MyClass alloc] init];
[_anObject dowWhateverInitAction];
}
return _anObject;
}
修改 我最初的问题是关于仅创建对象(而不是整个生命周期),但我添加了以下内容,以便它不会通过任何人:
- (void) dealloc {
self.anObject = nil;
}
/修改
练习的要点是在getter中使用setter。我已经将它用于所有类型的对象(ViewController,无数其他类型等)。我得到的好处是:
问题:
答案 0 :(得分:3)
此模式通常用作延迟加载技术,只有在首次请求时才会创建对象。
如果懒惰创建的对象需要大量的计算来创建,并且在时间紧迫的情况下被请求(这种情况下,使用这种技术没有意义),这种方法可能有一个缺点)。但是,如果对象快速创建,我会说这是一个合理的事情。
答案 1 :(得分:2)
你的实现唯一的错误(假设你还没有使用ARC)就是你有内存泄漏 - 使用setter意味着你的MyClass
实例被过度保留。您应该在初始化后释放或自动释放_anObject
,或直接分配其值而不是调用setter。
除此之外,这是完全正常的,当MyClass是一个不一定需要的对象并且可以轻松地重新创建时,它是一个很好的模式:你对内存警告的响应可以包括{{1释放实例的内存。
答案 2 :(得分:2)
它看起来像一个不错的lazy initialization。从哲学上讲,人们可以争辩说,缺点是吸气剂有副作用。但副作用在外面是不可见的,它是一种既定的模式。
答案 3 :(得分:2)
懒惰实例化是一种已建立的模式,Apple在其(可怕的)核心数据模板中使用它。
主要缺点是它过于复杂并且通常是不必要的。我已经失去了我已经看过的次数,在父对象初始化时简单地实例化对象会更有意义。
如果一个简单的解决方案同样好,那么请使用更简单的解决方案。是否有特殊原因导致在初始化父对象时无法实例化这些对象?也许子对象占用了大量内存,很少被访问?是否需要花费大量时间来创建对象,并且在应用程序的时间敏感部分初始化父对象?然后随意使用延迟实例化。但在大多数情况下,你应该更喜欢更简单的方法。
它也不是线程安全的。
关于你的优势:
仅在需要时创建对象。它使应用程序非常快(例如,在应用程序中有6-7个视图,只有一个在开始时创建)。
您是指视图还是视图控制器?你的陈述对于观点并没有多大意义。我通常不会发现自己需要在实例变量/属性中存储视图控制器,当我需要切换到它们并将它们推送到导航堆栈时,我将它们实例化,然后在我完成时弹出它们。
您是否尝试过不使用此模式的应用?关于性能的猜想经常是错误的。
我不必担心在使用之前创建一个对象......它会自动发生。
不,现在你不得不担心写一个特殊的吸气剂。这比简单的实例化更复杂,更容易出错。它还使您的应用程序逻辑和性能更难以理解和推理。
我不必担心第一次需要对象的位置......我只能访问该对象,就好像它已经存在一样,如果不存在,它就会被创建为新的。
在父对象初始化期间实例化它时,您不必担心这一点。
答案 4 :(得分:0)
是的,这是既定模式。我经常使用像这样的惰性实例化作为使用一堆设置代码来混淆-init
或-viewDidLoad
的替代方法。如果由于-init
中发生的事情导致该对象最终被创建,我会将值分配给实例变量而不是使用合成的setter。