我应该使用+ load来生成单例吗?

时间:2015-12-04 19:23:16

标签: objective-c singleton

我正在写一个单例类,我通常会这样做:

@interface MySingleton
+ (instancetype) instance;
@end

@implementation MySingleton
+ (instancetype) instance {
    static MySingleton *instance;
    if (!instance) {
        instance = [MySingleton new];
    }
    return instance;
}
@end

但我最近考虑过这种模式:

@interface MySingleton
+ (instancetype) instance;
@end

@implementation MySingleton
static MySingleton *instance;
+ (void) load {
    instance = [MySingleton new];
}
+ (instancetype) instance {
    return instance;
}
@end

我发现这更优雅,更容易理解,但这将是我第一次使用+load我有没有陷入任何陷阱?有什么理由这是个坏主意吗?

2 个答案:

答案 0 :(得分:3)

对于Swift代码,已弃用/删除了

+load。虽然现有的ObjC代码仍然会执行它(即使从Swift调用),新代码也不应该依赖它。 @ gnasher729引用的dispatch_once方法是强烈优选的,并且具有延迟的优点(+load减慢启动速度; dispatch_once在第一次使用之前不强制构造)。 dispatch_once Singleton甚至是Xcode中的内置代码片段。 Apple在Adopting Cocoa Design Patterns中提供了推荐的实现。

+ (instancetype)sharedInstance {
    static id _sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[self alloc] init];
    });

    return _sharedInstance;
}

(或在斯威夫特)

class Singleton {
    static let sharedInstance = Singleton()
}

sharedInstance的命名sharedFoo(或更好,Foo的{​​{1}})优先于instance。请参阅+[NSURLSesssion sharedSession]等。这将捕获ObjC中单身人士的真实本质,而不是真正单身人士。只有一个众所周知的例子。您通常可以使用+new+alloc自由实例化其他实例。 +instance听起来像+new一样,创建一个新的实例。 +sharedInstance清楚地表明这是其他呼叫者共享的实例。

作为附注,我提到近年来ObjC社区中的许多人gradually moving away from singletons因为他们在测试中创造的困难,他们创建全球可变状态以及一般缺乏灵活性。手动依赖注入(即仅设置属性或传递参数,而不是复杂的DI框架)一直在增长。这远非普遍,我并没有声称Singleton是ObjC中的反模式,但我鼓励你避免使用Singleton,因为它不是一个巨大的好处。多年来,它是我解决许多问题的首选方案,但时间和模式都有所改变。

答案 1 :(得分:1)

有一种广泛使用的模式来使用dispatch_once创建单例。绝对没有理由为什么有人会以任何不同的方式创建一个单身人士。相反,你想要使用一些非常模糊的技术(例如,一旦你切换到Swift,它就不起作用)。

顺便说一下,尝试调用一些类方法来配置你的单例,然后再创建它。不能用+ load工作。

顺便说一下,你通常的方式"不是线程安全的。