5

I have a base Store class with many methods that all stores inherit. Each store is a singleton. Right now, each store defines its own near-identical method:

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

Is there any way to craft a singleton method in a way that the method can simply be added to the base class and inherited by the subclasses?

4

2 に答える 2

5

simple/stupid に固執しますが、dispatch_once を使用します。

ジェネリックにしようとするとすぐに複雑になります。そしてバギー。

明示的なクラス名を指定した sharedInstance メソッドは明らかであり、プロジェクトで数回以上繰り返すことはまずありません。

ただし、1 つのクラスのサブクラスが多数ある場合は、識別子モデルに移行します。つまり、ストア インスタンスを識別子で検索できる抽象ストア クラスのキャッシュです。


このような初期化には、どちら+initializeか、またはさらに悪いことに、どちらも使用しないでください。+loadどちらも非決定論的であり、アプリ内の他のサブシステムに関連する実行順序は、一見無害な変更でかなり変動する可能性があります。

完全に決定論的な初期化を行う方がはるかに優れています。applicationDidFinishLaunching:アプリでこの特定のサブシステムを明示的に初期化するコールアウト (または他のいずれか) を追加します。従うのは簡単で、宣言と使用の両方で明示的であり、コードベースが進化しても奇妙な方法で動作が変わることはありません。

于 2013-05-16T02:36:23.690 に答える
2

1 つの store を使用するのではなく、クラス名をキーとしてstatic SubStore * store = nil;使用する a を使用できます。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;
}

...私のプログラムでこれを行うことはありません。

于 2013-05-16T07:15:26.997 に答える