【问题标题】:Objective-C - dynamic singleton initializer?Objective-C - 动态单例初始化器?
【发布时间】:2013-05-16 02:26:11
【问题描述】:

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

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

有没有什么方法可以制作单例方法,使该方法可以简单地添加到基类并由子类继承?

【问题讨论】:

  • 我已经尝试过,但从未找到方法。另外,为了线程安全,您应该使用dispatch_once 块而不是if(!store)
  • 我在关注图书代码。我会调查 dispatch_once。

标签: ios objective-c inheritance


【解决方案1】:

坚持简单/愚蠢,但使用 dispatch_once。

一旦您尝试使其通用化,它就会变得复杂。和越野车。

具有显式类命名的 sharedInstance 方法非常明显,您不太可能在项目中重复多次。

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


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

完全确定性的初始化要好得多。在您的 applicationDidFinishLaunching:(或其他之一)中添加一个标注,明确初始化您的应用程序中的这个特定子系统。它易于遵循,在声明和使用中都明确,并且不会随着代码库的发展而以奇怪的方式改变行为。

【讨论】:

  • 我经常把那种初始化代码放在+initialize里。 ObjC 运行时确保该方法只被调用一次。
  • @zneak 这并不完全正确。如果您的 A 类具有 initialize 方法,而 B 类扩展 A 并且 B 类没有实现 initialize 方法,则 A 类的 initialize 方法将被调用两次 - 一次是 A 是第一个引用以及何时首次引用 B。
  • +load 每个类/类别仅调用一次。
【解决方案2】:

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

简单地说:

#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;
}

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

【讨论】:

  • 你会用什么代替?
  • @StefanKendall 我是那些抱怨/不鼓励单身人士的人之一 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多