Objective-C - 动态单例初始化器?

时间:2013-05-16 02:26:11

标签: ios objective-c inheritance

我有一个基类Store类,其中包含所有商店继承的许多方法。每家商店都是单身人士。现在,每个商店都定义了自己几乎相同的方法:

+ (Store *)instance {
    static SubStore *store = nil;
    if (!store) {
        store = (SubStore *) [[super allocWithZone:nil] init];
        [store setupDefaults];
    }
    return store;
}

有没有办法以一种方式制作单例方法,该方法可以简单地添加到基类并由子类继承?

2 个答案:

答案 0 :(得分:5)

坚持使用simple / stupid,但请使用dispatch_once。

一旦你试图使它变得通用,就会变得复杂。而且越野车。

具有显式类命名的sharedInstance方法显而易见,并且您不太可能在项目中重复多次。

但是,如果您有一个类的许多子类,则转移到标识符模型。即抽象存储类上的缓存,可以按标识符查找存储实例。


我避免使用+initialize或更糟糕的+load进行此类初始化。两者都是非确定性的,因为它们与应用程序中其他子系统相关的执行顺序可能会因看似无害的变化而变化很大。

完全确定性初始化要好得多。在applicationDidFinishLaunching:(或其中一个)中添加一个标注,在您的应用中明确初始化此特定子系统。在声明和使用中都很容易理解,并且在代码库发展时不会以奇怪的方式改变行为。

答案 1 :(得分:2)

您可以使用使用类名作为键的static SubStore * store = nil;,而不是使用一个商店NSMutableDictionary

简言之:

#import <Foundation/Foundation.h>

@interface MONStore : NSObject
- (NSString *)nameOfMostPopularItem;
@end

@implementation MONStore

+ (instancetype)sharedStore
{
    // lazy population - not thread safe
    static NSMutableDictionary * stores = nil;
    if (nil == stores) {
        stores = [NSMutableDictionary new];
    }
    NSString * key = NSStringFromClass([self class]);
    if (nil == [stores objectForKey:key]) {
        [stores setObject:[self new] forKey:key];
    }
    return [stores objectForKey:key];
}

- (NSString *)nameOfMostPopularItem
{
    return nil;
}

@end

@interface MONMusicStore : MONStore
@end

@implementation MONMusicStore
- (NSString *)nameOfMostPopularItem { return @"Guitar Strings"; }
@end

@interface MONPetStore : MONStore
@end

@implementation MONPetStore
- (NSString *)nameOfMostPopularItem { return @"Puppies"; }
@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSLog(@"--- Shopping List ---\nMusic Store:\n\t%@\n\nPet Store:\n\t%@\n",
                    [MONMusicStore sharedStore].nameOfMostPopularItem,
                    [MONPetStore sharedStore].nameOfMostPopularItem
                    );
    }
    return 0;
}

...不是说我会在我的程序中这样做。