單例模式我們平時經(jīng)常使用镣典,這種模式涉及到一個單一的類渔期,該類負責創(chuàng)建自己的對象运吓,同時確保只有單個對象被創(chuàng)建渴邦。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問拘哨,不需要實例化該類的對象谋梭。
有幾個非常重要的問題。
單例類只能有一個實例倦青。
單例類必須自己創(chuàng)建自己的唯一實例瓮床。
單例類必須給所有其他對象提供這一實例。
其實我們在平時項目中产镐,很少注意隘庄,如何避免子類繼承我們的單例類。
如何來實現(xiàn)一個嚴格的單例
我們平時是這么使用的癣亚。
static UserInfoManagerCenter *center = nil;
+ (instancetype)managerCenter {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
center = [[UserInfoManagerCenter alloc] init];
});
return center;
}
那么如何避免子類繼承我們峭沦,避免使用init方法來創(chuàng)建對象呢?
我們可以在dispatch_once外面做下判斷逃糟,如何他使用了繼承吼鱼,調用了managerCenter直接崩潰。
static UserInfoManagerCenter *center = nil;
+ (instancetype)managerCenter {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
center = (UserInfoManagerCenter *)@"UserInfoManagerCenter";
center = [[UserInfoManagerCenter alloc] init];
});
//防止子類使用
if (![NSStringFromClass([self class]) isEqualToString:@"UserInfoManagerCenter"]) {
//#define NSParameterAssert(condition) NSAssert((condition), @"Invalid parameter not satisfying: %@", @#condition)
//ios 是這么定義NSParameterAssert的
//傳入nil會導致app崩潰
NSParameterAssert(nil);
}
return center;
}
那么如何避免子類調用父類的init方法來創(chuàng)建對象呢绰咽?
重寫父類的init方法菇肃,同樣如果是子類調用父類的init方法,直接崩潰
- (instancetype)init {
NSString *string = (NSString *)center;
if ([string isKindOfClass:[NSString class]] == YES && [string isEqualToString:@"UserInfoManagerCenter"]) {
self = [super init];
if (self) {
// 防止子類使用
NSString *classString = NSStringFromClass([self class]);
if (![classString isEqualToString:@"UserInfoManagerCenter"]) {
NSParameterAssert(nil);
}
}
return self;
} else {
return nil;
}
}