单例的必要认识(深刻理解)
来源:互联网 发布:淘宝购物节直播 编辑:程序博客网 时间:2024/05/20 05:53
最近我面试人家,问他对单例的认识,他对单例的基本认识、创建方式回答全对,只有一点吞吞吐吐。
单例的认识
单例模式:单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例
系统单例:
1、UIApplication(应用程序实例)
2、NSNotificationCenter(消息中心):
3、NSFileManager(文件管理):
4、NSUserDefaults(应用程序设置):
5、NSURLCache(请求缓存):
6、NSHTTPCookieStorage(应用程序cookies池):
1.单例模式的要点:
显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
2.单例模式的优点:
1.安全性和唯一性:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例。单例类也可以防止他人复制(copy),保留(retain)或释放(release)实例。如果您发现需要,您可以创建自己的单例。例如,如果您有一个类为应用程序中的其他对象提供声音,则可以将其设为单例。
2.灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程
创建步骤
1、为你的单例类声明一个静态的实例(声明静态全局变量),并且初始化它的值为nil; eg:
static TestSingleton *testSingleton = nil;
这样,在获取实例的方法中,只有在静态实例为nil的时候,产生一个你的类的实例,这个实例通常被称为共享的实例;
2、重写allocWithZone方法,用于确定:不能够使用其他的方法创建我们类的实例,限制用户只能通过获取实例的方法得到这个类的实例。所以我们在allocWithZone方法中直接返回共享的类实例;
3、写+(instancetype)shareSingleton的函数体
创建方法
一、传统方法
+(instancetype)shareSingleton{ static Singleton *singleton = nil; if (singleton == nil){ singleton = [[self alloc] init]; } return singleton; }
二、推荐方法(GCD)
+(instancetype)shareSingleton{ static Singleton *singleton = nil; //给单例加一个线程锁 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ singleton = [[Singleton alloc] init]; }); return singleton;```三、线程加锁方法(不推荐使用)
+(instancetype)shareSingleton{
static Singleton *singleton = nil;
@synchronized(self) {
singleton = [[Singleton alloc] init];
}
return singleton;
}“`
注:“线程加锁方法”这样性能不是很好,因为每次调用+ (instancetype)sharedSingleton函数都会付出取锁的代价
吞吞吐吐:
但我问他,这样写的话是保证了线程安全,但通过自带的
alloc
或者new
来进行实例化,还是不能保证该对象只被创建一次,如何避免呢?他就回答不上了,其实很简单:
- .h头文件:
@interface TestSingleton : NSObject@property (nonatomic, copy)NSString *testStr;+ (TestSingleton *)shareinstance;@end
- .m文件:
+ (TestSingleton *)shareinstance { static TestSingleton *testSingleton = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{//testSingleton = [self singletonAlloc]; //后面使用该创建方法 testSingleton = [self new];//[[self alloc]init]; }); return testSingleton;}
//我们需要重载alloc、new
方法
+ (instancetype)singletonAlloc{ return [super alloc];}+ (instancetype)alloc{//加断言,使用alloc会蹦,并且reason提示 NSAssert(NO, @"不要用alloc,要使用singletonAlloc方法创建"); return nil;}+ (instancetype)new{ return [self alloc];}+ (TestSingleton *)shareinstance { static TestSingleton *testSingleton = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ testSingleton = [[self singletonAlloc]init]; }); return testSingleton;}
重载了alloc、allocWithZone和new方法,在alloc方法中加上断言来提醒,让用户不能使用alloc创建实例。
扩展一:(面试经常问到)
普通类允许调用者根据需要创建尽可能多的类的实例,而对于单例类,每个进程只能有一个类的实例,保证了单例数据的唯一性,安全性
调用下面方法:
-(void)testSigleton{ /** * singleton和singleton2是同一个对象; */ TestSingleton *singleton = [TestSingleton shareinstance]; TestSingleton *singleton2 = [TestSingleton shareinstance]; if (singleton == singleton2) { NSLog(@"singleton == singleton2"); } NSLog(@"singleton地址:%@",singleton); NSLog(@"singleton2地址:%@",singleton2);}
打印如下
SingletonTest[1598:54880] singleton == singleton2 SingletonTest[1598:54880] singleton地址:<TestSingleton: 0x60000001e930> SingletonTest[1598:54880] singleton2地址:<TestSingleton: 0x60000001e930>
可以看出地址一样,证明单例只会创建一个静态变量,全局唯一
扩展二:(宏定义单例)
作用:有时在项目中需要创建好多个单例,把单例的代码定义为宏,则可以省去重复代码,节省时间。
/** * 在.h文件中定义的宏,arc * * DWSingletonH(classname, accessorMethodName) 这个是宏 * 在外边我们使用 “DWSingletonH(classname, accessorMethodName)” 那么在.h文件中,定义了一个方 法"+ (instancetype)accessorMethodName;" * */#define DWSingletonH(classname, accessorMethodName) + (instancetype)accessorMethodName;/** * 在.m文件中处理好的宏 arc * * DWSingletonM(classname, accessorMethodName) 这个是宏,因为是多行的东西,所以每行后面都有一个"\",最后一行除外 */#define DWSingletonM(classname, accessorMethodName) \static classname *instance_ = nil;\+ (instancetype)accessorMethodName{\static dispatch_once_t onceToken;\dispatch_once(&onceToken, ^{\instance_ = [[self alloc] init];\});\return instance_;\}\+ (instancetype)allocWithZone:(struct _NSZone *)zone{\static dispatch_once_t onceToken;\dispatch_once(&onceToken, ^{\instance_ = [super allocWithZone:zone];\});\return instance_;\}\- (id)copyWithZone:(NSZone *)zone{\return instance_;\}
把上面代码用一个Header File
文件里面,然后就可以在其他类快速创建单例了
* .h头文件:
@interface Singleton2 : NSObject//@property double t;DWSingletonH(Singleton2, shareInstance)@end
- .m文件:
@implementation Singleton2DWSingletonM(Singleton2, shareInstance)@end
- 单例的必要认识(深刻理解)
- 单例模式的深刻理解及最优法例子
- synchronized的深刻认识
- synchronized的深刻认识
- synchronized的深刻认识
- synchronized的深刻认识
- synchronized的深刻认识
- 由类实例对象为static引发对单例模式的深刻理解
- 从简单的选择排序入手,深刻理解程序
- 单例模式的理解认识 练习笔记
- java synchronized的深刻认识
- new关键的深刻认识
- 句柄的深刻理解
- Layout_weight的深刻理解
- 对于c++面向对象的深刻认识和理解--哲学角度看问题(源生论)
- 让我有深刻认识的笑话,思考深刻啊
- 对DataSetHelper类的一些深刻认识
- 关于UILocalNotification一些更深刻的认识
- Matlab验算拉格朗日中值定理
- Python的文件类型、变量以及数值和字符串
- lua math库
- php取不定个数数组交集、并集(以空间换时间)
- 关于cmd中出现无法识别命令的问题(xx运行的程序不是内部或外部命令,也不是可执行的程序)
- 单例的必要认识(深刻理解)
- TCP网络编程
- JavaSript模块规范
- 如何上线自己的第一个网站?
- Linux下GCC的安装(在线模式)
- 基于神经网络的2D摄像头的静态手势识别系统实现
- IT行业风投
- Linux设备驱动入门 -hello world
- tableviewcell 动态计算cell高度导致tableview滑动卡顿怎么办??