ios 开发----单利
1、=====方法一 、废除 init / new 方法
// .h文件中
@interface UserManager : NSObject
+ (UserManager *) sharedManager; //添加类方法
// .m文件中
第一步、废除原有 初始化方法 抛出异常
- (instancetype) init {
@throw [NSException exceptionWithName:@"" reason:@"不能调用init/new方法初始化CDUserManager对象" userInfo:nil];
}
第二步、方法重写 方法私有化
- (instancetype) initPrivate {
if (self = [super init]) {
//设置属性 自定义
User *user = [[User alloc] init];
user.username = @"AAA";
user.password = @"123456";
user.email = @"admin@1000phone.com";
}
return self;
}
第三步、创建单例对象(唯一的)
+ (UserManager *) sharedManager{
static UserManager *manager = nil; //静态实例 并初始化
@synchronized (self) { // 同步保护 只允许一个线程进入 排队等候
if (!manager) { //如果为空 则新建 分配内存 初始化为私有
manager = [[self alloc] initPrivate];
}
}
return manager;//返回本类型 实例
}
2、如果你用 init 或 new 来创建对象 就会抛出异常
UserManager *uuu = [UserManager new];
UserManager *uuu = [[UserManager alloc]init];
3、====方法二 、可以 init / new 方法
为了防止别人不小心利用alloc/init方式创建示例,也为了防止别人故意为之,我们要保证不管用什么方式创建都只能是同一个实例对象,这就得重写另一个方法,实现如下:
可以将property的初始化或者默认值设置放到dispatch_once 的block内部
写法一、
static HLTestObject *instance = nil;
+ (instancetype)sharedInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 设置属性
instance = [[[self class] alloc] init];
instance.height = 10;
instance.object = [[NSObject alloc] init];
instance.arrayM = [[NSMutableArray alloc] init];
});
return instance;
}
//重写方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
写法二、
static HLTestObject *instance = nil;
+ (instancetype)sharedInstance{
return [[self alloc] init];
}
- (instancetype)init{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super init]; //==
//设置属性
instance.height = 10;
instance.object = [[NSObject alloc] init];
instance.arrayM = [[NSMutableArray alloc] init];
});
return instance;
}
//重写方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
//下面的方法 是为 copy mutableCopy 得到的对象也是唯一的
//copy在底层 会调用copyWithZone:
- (id)copyWithZone:(NSZone *)zone{
return instance;
}
+ (id)copyWithZone:(struct _NSZone *)zone{
return _instance;
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone{
return _instance;
}
可以用如下图的三种方法创建对象,得到的都是同一个
4、====dispatch_once 与 @synchronized (self) 的比较
使用dispatch_once可以简化代码并且彻底保证线程安全,开发者无需担心加锁或同步。此外,dispatch_once更高效,它没有使用重量级的同步机制,若是那样做的话,每次运行代码前都要获取锁。相反,此函数采用“原子访问”来查询标记,以判断其所对应的代码原来是否已经执行过
5、把单利抽出一个宏,以ARC为例