全局变量作为单例的别名?

时间:2009-04-26 00:35:36

标签: objective-c cocoa oop naming-conventions singleton

我正在开发一个Cocoa(Touch)应用程序,并且我必须在不同的视图和控制器之间保留某些数据(如自己的设备信息和位置列表)。

我想过将它作为实例变量存储在我的App Delegate中,但是对代理进行寻址是非常麻烦的(每次我想访问位置数组时都没有快乐键入[[[UIApplication sharedApplication] delegate] locations],而且很多地方),所以我想为代理引入某种别名(la NSApp),但除了NSApp之外,我还没有在其他Cocoa应用程序中经常看到这种情况。

我还想进一步为我的单例类引入别名,所以不是[State sharedState],而是为什么不将类重命名为_State并将它的一个实例称为State?< / p>

4 个答案:

答案 0 :(得分:1)

我可能会写一个类似于LocationManager的类,它给出了一个带有[LocationManager sharedManager]或类似功能的单例。通过委托调用会破坏封装(并且您通过3个对象调用来实现)。即使是NSApp风格的#define也无法解决这个问题。

答案 1 :(得分:1)

使用方法调用来获取单例的主要目的是可以懒惰地准备单例。例如:

static State sharedStateInstance;

@implementation State
+ (id)sharedState {
    if (!sharedStateInstance)
        sharedStateInstance = /* Allocate instance */;
    return sharedStateInstance;
}
@end

所以这意味着如果没有代码调用+sharedState,则不会花费任何资源来创建它。

此外,如果将来出现其他需求,可以在一个地方改进此代码,例如确保每个线程有一个实例,或者所有线程的共享实例(然后需要在初始化时锁定代码)。 / p>

答案 2 :(得分:1)

Cocoa鼓励使用[Foo sharedFoo]而不是全局Foo对象有几个原因。

[Foo sharedFoo]可以在第一次使用时自动实例化。

用大写字母命名实例非常令人困惑,因为它看起来像一个类,鼓励错误。命名的一致性是良好Objective-C的核心。编译器不能保护您免受各种各样的错误,因为ObjC是高度动态的。良好的命名和一致性自律是导致无错Cocoa的原因。

平行度:

Foo *foo = [Foo sharedFoo];
Foo *foo = [[[Foo alloc] init] autorelease];
Foo *foo = [Bar fooAtIndex:0];

所有这三个在同一个程序中可能是合法的。仅仅因为存在单例实例并不意味着也没有其他实例。 NSNotificationCenter就是一个很好的例子。它是一个单例,但您可以创建其他实例(并且有理由这样做)。

可以全局修改全局变量。 sharedInstance不可以。例如,如果State是全局变量(而不是类),则State=nil在程序中的任何位置都是合法的。这破坏了封装,并且是编译器无法捕获的state=nil的简单错字。如果State是一个类,那么编译器可以捕获这个简单的错误。

Cocoa命名的许多规则是为了鼓励高度可读的代码,并在高度动态和松散类型的环境中最小化错误。就像Perl的use strict一样,在放弃我们拥有的小安全网之前,我们应该非常小心。

答案 3 :(得分:0)

#define FOO [[[UIApplication sharedApplication] delegate] locations]