Objective-c 单例基类

4

有没有一种用Objective-C创建单例模式的方法,使客户端代码可以获取其任何子类的共享实例?

我尝试过:

@interface Base : NSObject {}
+(id)instance;
@end

@implementation Base
static id _instance;
+(id)instance {
    if (!_instance) {
        _instance = [[self alloc] init];
    }
    return _instance;
}
@end

但是,调用任何子类的[AmazingThing instance]都只会返回通过此机制创建的第一个实例,无论_instance的类型是什么。有没有简单的解决方法?

编辑

我意识到(在回复已删除的答案时)我可以通过将实现更改为以下方式来实现我的目标:

static NSMutableDictionary *_instances;

+(id)instance {
    if (!_instances) {
        _instances = [[NSMutableDictionary alloc] init];
    }
    id instance = [_instances objectForKey:self];
    if (!instance) {
        instance = [[self alloc] init];
        [_instances setObject:instance forKey:self];
    }
    return instance;
}

现在它按预期工作。但我很想知道是否有更好的方法来做到这一点。


只是出于好奇,这个有什么使用案例吗? - ennuikiller
@ennuikiller 我正在制作一个实体/组件系统,为了原型设计的目的,我想要每个组件都有一个单例。 - sharvey
你的编辑是我情况下非常好的解决方案。谢谢! - Adem
4个回答

7
我会这样做:
+(id) instance
{
    static id theInstance = nil;
    if (theInstance == nil)
    {
        theInstance = [[self alloc] init];
    }
    return theInstance;
}

当然,您需要在每个子类中使用该方法才能为每个类获取不同的静态变量。但是,在基类头文件中创建一个#define

#define CREATE_INSTANCE           \
+(id) instance                    \
{                                 \
    static id theInstance = nil;  \
    if (theInstance == nil)       \
    {                             \
        theInstance = [[self alloc] init]; \
    }                             \
    return theInstance;           \
}

然后每个实现只需在其中定义即可:
@implementation SubClass

CREATE_INSTANCE

// other stuff

@end

你为什么使用 [self alloc] 而不是 [[self class] alloc]?使用后者,你只需要在基类中定义 + (id) instance。 - onmyway133
2
因为接收者self已经是类了。在每个子类中重新定义方法的原因是为了获取单例模式的不同静态变量,而不是基于子类自动发生的实例。 - JeremyP

1
如果使用Objective-C++是可以的。你可以有一个元编程的C++类来管理单例对象的生命周期。 这样,你就可以使用Singleton模式,并使用以下方式访问单例: Derived* d = Singleton<Derived>::get()。 更多参考资料,请查看http://src.chromium.org/viewvc/chrome/trunk/src/base/singleton_objc.h,这是Chrome如何实现它的方法。

谢谢,我会看一下的。我很好奇与我在更新中发布的解决方案相比,内存和性能上的改进会是什么样子。 - sharvey

0

0

只需使用EPPZSingleton

创建一个只能有一个子类的基类很简单,但当您开始创建越来越多的子类时,可能会出现意外行为。EPPZSingleton通过维护单例的共享集合来解决此问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接