所谓单例就是确保在程序运行过程中只创建一个对象实例。可以用于需要被多次广泛或者说多次使用的资源中,比如我们常见的网络请求类、工具类以及其它管理类等。iOS开发中常见的系统单例[UIApplication sharedApplication]、[NSUserDefaults standardUserDefaults]等。
一、单例模式的三大要点:
1、某个类只能有一个实例;
2、它必须自行创建这个实例;
3、它必须自行向整个系统提供这个实例。
二、单例模式优缺点
优点
1、提供了对唯一实例的受控访问。
2、由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。
3.因为单例模式的类控制了实例化的过程,所以类可以更加灵活修改实例化过程。
缺点
1、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
2、单例类的职责过重,在一定程度上违背了“单一职责原则”。
三、单例的实现
基本步骤:
1、 为单例对象创建一个静态实例,可以写成全局的,也可以在类方法里面实现,并初始化为nil;
2、 实现一个实例构造方法,检查上面声明的静态实例是否为nil,如果是,则创建并返回一个本类的实例;
3、 重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例;
4、适当实现copyWithZone,mutableCopyWithZone,非arc下还需要实现release和autorelease方法。
下面新建一个singleton类,在Singleton.h上实现如下:
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
+(instancetype)sharedInstance;
@end
在Singleton.m上实现如下:
#import "Singleton.h"
//创建全局静态实例
static Singleton *singleton = nil;
@implementation Singleton
//使用GCD的方式来使用单例,效果最高的
+(instancetype)sharedInstance{
//防止本方法被多次调用而引发冲突
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
//此处的代码仅会被调用一次
singleton = [[Singleton alloc] init];
});
return singleton;
}
//如果允许另外使用alloc/new创建非单例对,刚不必重写此方法
+(instancetype)allocWithZone:(struct _NSZone *)zone{
//防止本方法被多次调用而发生冲突
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//此处仅会调用一次
singleton = [super allocWithZone:zone];
});
return singleton;
}
//以下代码仅在非ARC环境下需要
#if !__has_feature(objc_arc)
-(NSUInteger)retainCount{
//返回一个最大的整数,表示此数字没有意义
return NSInteger;
}
-(id)retain{
//直接返回自身,不改变引用计数器
return self;
}
-(oneway void)release{
//什么都不用做
}
-(id)autorelease{
//直接返回自身,不改变引用计数器
return self;
}
#endif
@end
打印看看:
Singleton *singleton = [Singleton sharedInstance];
NSLog(@"singleton= %@",singleton); //singleton = <Singleton: 0x7a74c120>
小案例:
新建一个DataManager类,在DataManager.h上实现如下:
#import <Foundation/Foundation.h>
@interface DataManager : NSObject
+(instancetype)shareManager;
@property (nonatomic,copy) NSString *UserName;
@property (nonatomic,copy) NSString *setNumber;
@end
在DataManager.m类上实现如下:
#import "DataManager.h"
#define KName @"managerName"
#define KNubmer @"managerNumber"
@interface DataManager ()
@property (nonatomic,strong)NSUserDefaults *userDefault;
@end
@implementation DataManager
@synthesize UserName = _UserName;
@synthesize setNumber = _setNumber;
//创建单例类
static DataManager *dataManager = nil;
+(instancetype)shareManager{
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
dataManager = [[DataManager alloc]init];
});
return dataManager;
}
//懒加载
-(NSUserDefaults *)userDefault{
if (!_userDefault) {
_userDefault = [NSUserDefaults standardUserDefaults];
}
return _userDefault;
}
//保存字符串类型的
-(void)setUserName:(NSString *)UserName{
_UserName = UserName;
[self.userDefault setObject:_UserName forKey:KName];
[self.userDefault synchronize];
}
//获取
-(NSString *)UserName{
_UserName = [self getStringNil:[self.userDefault objectForKey:KName]];
return _UserName;
}
//保存NSInteger类型数字
-(void)setNubmer :(NSInteger) isNubmer{
_setNumber = isNubmer;
[self.userDefault setInteger:_setNumber forKey:KNubmer];
}
//取出数字
-(NSInteger)setNubmer{
_setNumber = [self.userDefault integerForKey:KNubmer] ;
return _setNumber;
}
- (NSString *)getStringNil:(NSString *)string
{
if ([string isKindOfClass:[NSNull class]] || !string ) {
string = @"";
}
string = [NSString stringWithFormat:@"%@",string];
return string;
}
@end
调用方法
//保存
[[DataManager shareManager] setUserName:@"name"];
//读取
NSString *string = [DataManager shareManager].UserName;
NSLog(@"string = %@ ",string); //输出string = name