关于C#:在单例上实现alloc

Implement alloc on a singleton

我希望在我的系统中有一个singleton,但不希望呼叫者通过某种"sharedInstance"方法访问它,我希望他们能够不知道他们正在使用singleton,换句话说,我希望呼叫者能够说:

1
MyClass *dontKnowItsASingleton = [[MyClass alloc] init];

为此,我尝试重写alloc,如下所示:

1
2
3
4
5
6
7
8
9
10
11
// MyClass.m

static MyClass *_sharedInstance;

+ (id)alloc {

    if (!_sharedInstance) {
        _sharedInstance = [super alloc];
    }
    return _sharedInstance;
}

我的问题是:这样可以吗?它似乎有效,但我从未重写过alloc。另外,如果可以的话,我是否可以一直使用这种技术,而不是在我做过的一次调度方法?…

1
2
3
4
5
6
7
8
9
+ (id)sharedInstance {

    static SnappyTV *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[self alloc] init];
    });
    return _sharedInstance;
}


如@h2co3所述,您生产单件产品的方法是可以接受的,但不是螺纹安全。更传统的方法是将您的分配和比较包装在一个@synchronized块中,这样可以减少多线程访问,但是覆盖+alloc并不是实现已经不稳定的模式的最佳方法。


如果有人来找我,我认为这里有一个整合了所有好建议的解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
+ (id)alloc {

    @synchronized(self) {
        if (!_sharedInstance) {
            _sharedInstance = [super alloc];
        }
        return _sharedInstance;
    }
}

- (id)init {

    @synchronized(self) {
        static BOOL init = NO;
        if (!init) {
            init = YES;
            self = [super init];
        }
    }
    return self;
}

多亏了@h2co3的线程安全问题,@codafi的线程安全处方,@rob mayoff的ARC下init的危险。今天我得到了最优秀和最聪明的人的帮助!


我认为您应该利用初始化方法:

1
2
3
4
5
6
7
8
9
10
+ (void) initialize
{
    _sharedInstance= [[self alloc]init];
}


+ (id)sharedInstance
{
    return _sharedIntsance;
}