Objective-C 中的单例
来源:互联网 发布:卖家怎么加入农村淘宝 编辑:程序博客网 时间:2024/05/21 16:57
其实对于单例,在程序开发中非常的常见。
最近我也对单例进行了一些更细致的研究。
在我的程序中,单例一般是这么去写的:
+ (DataSource *)shareInstance
{
static DataSource *instance = nil;
if (instance == nil)
{
instance = [[DataSource alloc] init];
}
return instance;
}
在我做过的十几个软件中,一直都是这么去写的。
但是在我前段时间看书的过程中,发现跟书中的例子不太一样,所以做了一下研究。
发现,这样的单例是不可靠的。因为如果开发者一直调用 [DataSource shareInstance] 当然没有问题, 但是如果有人调用 [ DataSource alloc] 这样的方法,就会出现多个对象。
所以,我们需要实现“严格”意义的单例。
需要克服两个障碍:
1. 发起调用的对象不能以其他分配方式实例化单例对象。
2.对单例对象实例化的限制应该与引用计数内存模型共存。
下面我们看一下官方给出的单例模式的例子
static MyGizmoClass *sharedGizmoManager = nil;
+ (MyGizmoClass*)sharedManager
{
if (sharedGizmoManager == nil) {
sharedGizmoManager = [[super allocWithZone:NULL] init];
}
return sharedGizmoManager;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedManager] retain];
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax; //denotes an object that cannot be released
}
- (void)release
{
//do nothing
}
- (id)autorelease
{
return self;
}
他的方式是重写release,retain,retainCount,autoRelease,allocWithZone和copyWithZone等方法。
1 重写allocWithZone和copyWithZone的目的是外部在多次调用alloc的时候,内部能够确保对象只创建了一次。
2 重写release、retain、autorelease、retainCount避免单件对象被外部释放。
两个缺点:
A 隐藏了在对象生命周期管理时出现的bug。
对对象的引用出错的原因必然是程序本身的错误,隐藏对象的引用计数错误就是隐藏了应用程序的错误。
从工程角度上讲,崩溃要比程序的逻辑错误容易定位。
解决方法:建议在release、retain、autorelease里面做一些内部的调用次数监控,一旦发现外部调用不平衡就发出警告。
B 对象可以被多次init。
多次调用init导致错误的可能性还是有的,这种错误包括重复加载某些资源降低性能。
解决方法:重写init并在内部判重就可以了。
C 多线程安全
解决方法:在sharedManager中加入同步代码块,代码:
+ (MyGizmoClass*)sharedManager
{
@synchronized(self) {
if (sharedGizmoManager == nil) {
sharedGizmoManager = [[super allocWithZone:NULL] init];
}
}
return sharedGizmoManager;
}
最近我也对单例进行了一些更细致的研究。
在我的程序中,单例一般是这么去写的:
+ (DataSource *)shareInstance
{
static DataSource *instance = nil;
if (instance == nil)
{
instance = [[DataSource alloc] init];
}
return instance;
}
在我做过的十几个软件中,一直都是这么去写的。
但是在我前段时间看书的过程中,发现跟书中的例子不太一样,所以做了一下研究。
发现,这样的单例是不可靠的。因为如果开发者一直调用 [DataSource shareInstance] 当然没有问题, 但是如果有人调用 [ DataSource alloc] 这样的方法,就会出现多个对象。
所以,我们需要实现“严格”意义的单例。
需要克服两个障碍:
1. 发起调用的对象不能以其他分配方式实例化单例对象。
2.对单例对象实例化的限制应该与引用计数内存模型共存。
下面我们看一下官方给出的单例模式的例子
static MyGizmoClass *sharedGizmoManager = nil;
+ (MyGizmoClass*)sharedManager
{
if (sharedGizmoManager == nil) {
sharedGizmoManager = [[super allocWithZone:NULL] init];
}
return sharedGizmoManager;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedManager] retain];
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax; //denotes an object that cannot be released
}
- (void)release
{
//do nothing
}
- (id)autorelease
{
return self;
}
他的方式是重写release,retain,retainCount,autoRelease,allocWithZone和copyWithZone等方法。
1 重写allocWithZone和copyWithZone的目的是外部在多次调用alloc的时候,内部能够确保对象只创建了一次。
2 重写release、retain、autorelease、retainCount避免单件对象被外部释放。
两个缺点:
A 隐藏了在对象生命周期管理时出现的bug。
对对象的引用出错的原因必然是程序本身的错误,隐藏对象的引用计数错误就是隐藏了应用程序的错误。
从工程角度上讲,崩溃要比程序的逻辑错误容易定位。
解决方法:建议在release、retain、autorelease里面做一些内部的调用次数监控,一旦发现外部调用不平衡就发出警告。
B 对象可以被多次init。
多次调用init导致错误的可能性还是有的,这种错误包括重复加载某些资源降低性能。
解决方法:重写init并在内部判重就可以了。
C 多线程安全
解决方法:在sharedManager中加入同步代码块,代码:
+ (MyGizmoClass*)sharedManager
{
@synchronized(self) {
if (sharedGizmoManager == nil) {
sharedGizmoManager = [[super allocWithZone:NULL] init];
}
}
return sharedGizmoManager;
}
- Objective-C 中的单例
- Objective-c中的单例设计模式
- Objective-C中的单例模式
- Objective-C中的单例模式
- Objective-C中的单例模式(singleton)
- Objective-C 单例
- Objective-C单例
- Objective-C中的设计模式之单例模式
- Objective-C单例实现
- Objective C--单例模式
- Objective C--单例模式
- Objective C 单例模式
- Objective C--单例模式
- Objective C 单例实现
- Objective-C单例模式
- Objective C--单例模式
- Objective-C单例模式
- Objective-C 单例模式
- 在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序
- Aspose.Cells控件的强大导出功能_控件资料_慧都... 网址
- linux find prune exec 排除某目录或文件 执行
- Why you don't want real-time analytics to be exact
- 软RAID与硬RAID的区别
- Objective-C 中的单例
- autosys start_mins
- 七夕感怀
- struts2发送json语句
- C#使用摄像头拍照
- NSIS 在卸载程序时调用bat
- VC以裸函数的形式内联汇编
- 程序代码中含有线程pthread_create时需要对编译选项的修改
- 每一首歌曲