单例模式应该是设计模式中很简单的一种,最近项目上有用到,写篇log记录一下
一:什么是单例模式
一个类在全局只允许有一个实例,全局访问的都是这个同一个实例,并且这个实例的生命周期被延长了,这个实例在程序的整个生命周期中都会存在
栗子:
有一个UserModel的类,你需要实例化出来一个对象userModel,在app全局都会用到userModel这个对象,然后你又希望这个userModel一直存在内存中,随时都能拿到里面的内容。这就是一个很好的单例的应用
二:实现单例模式
+ (instancetype)defaultModel;
+ (instancetype)defaultModel {
static ELUserModel *_instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_instance == nil) {
_instance = [[self alloc] init];
}
});
return _instance;
}
用define快速声明单例
#define DECLARE_SINGLETON(method) \
+ (instancetype)method;
#define DEFINE_SINGLETON(clazz, method) \
+ (instancetype)method { \
static clazz *instance = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
instance = [[clazz alloc] init]; \
}); \
return instance; \
}
三:需要注意的问题
OC语言的构造方法都是公开的,外部还是可以通过alloc init方法构造出新的对象,导致会有多个实例,单例失败。
这个问题有两种解决方案
1:在创建对象的时候哦,无论是alloc或者new都会调用-(id)copyWithZone:(NSZone *)zone,-(id)mutableCopyWithZone:(NSZone *)zone
这几个方法
所以我们可以重写这些方法
-(id)copyWithZone:(NSZone *)zone{
return [ELUserModel defaultModel];
}
-(id)mutableCopyWithZone:(NSZone *)zone{
return [ELUserModel defaultModel];
}
2:禁用自带的构造方法,告诉使用者,这是一个单例,否则编译不过
+(instancetype) alloc __attribute__((unavailable("call sharedInstance instead")));
+(instancetype) new __attribute__((unavailable("call sharedInstance instead")));
-(instancetype) copy __attribute__((unavailable("call sharedInstance instead")));
-(instancetype) mutableCopy __attribute__((unavailable("call sharedInstance instead")));