- 版权声明:本文为博主原创文章,未经博主允许不得转载。
单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
1.单例模式的要点:
显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
2.单例模式的优点:
1.实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例。
2.灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程
iOS中的单例模式
- 在objective-c中要实现一个单例类,至少需要做以下四个步骤:
1、为单例对象实现一个静态实例,并初始化,然后设置成nil,
2、实现一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例,
3、重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例,
4、适当实现allocWitheZone,copyWithZone,release和autorelease。
- 下面以SurveyRunTimeData为例子:
static MyClass *class = nil;
@implementation MyClass
+(MyClass *)sharedMyClass{
@synchronized(self){ //为了确保多线程情况下,仍然确保实体的唯一性
if (!class) {
[[self alloc] init]; //该方法会调用 allocWithZone
}
}
return class;
}
+(id)allocWithZone:(NSZone *)zone{
@synchronized(self){// //为了确保多线程情况下,仍然确保实体的唯一性
if (!class) {
class = [super allocWithZone:zone]; //确保使用同一块内存地址
return class;
}
}
return nil;
}
-(id)init
{
if(class){
return class;
}
if(self = [super init]){
//进行一些初始化
}
return self ;
}
- (id)copyWithZone:(NSZone *)zone;{
return self; //确保copy对象也是唯一
}
-(id)retain{
return self; //确保计数唯一
}
- (unsigned)retainCount
{
return UINT_MAX; //装逼用的,这样打印出来的计数永远为-1
}
- (id)autorelease
{
return self;//确保计数唯一
}
- (oneway void)release
{
//重写计数释放方法 do nothing
}
@end ```
>再调试
MyClass *A = [[MyClass alloc] init];
NSLog(@"A:%@",A);
MyClass *B = [MyClass sharedMyClass];
NSLog(@"B:%@",B);
MyClass *C = [A copy];
NSLog(@"C:%@",C);```
打印出的是
A:<MyClass: 0x6a1e130>
B:<MyClass: 0x6a1e130>
C:<MyClass: 0x6a1e130>```
>都是指向同一块内存地址
- 然而这个人(<http://eschatologist.net/blog/?p=178>)觉的繁琐,所以给出如下实现:
@interface SomeManager : NSObject
- (id)sharedManager;
@end
/* 非线程安全的实现 */
@implementation SomeManager
-
(id)sharedManager {
static id sharedManager = nil;if (sharedManager == nil) {
sharedManager = [[self alloc] init];
}return sharedManager;
}
@end
/* 线程安全的实现 */
@implementation SomeManager
static id sharedManager = nil;
(void)initialize {
if (self == [SomeManager class]) {
sharedManager = [[self alloc] init];
}
}(id)sharedManager {
return sharedManager;
}
@end ```
自苹果引入了
Grand Central Dispatch (GCD)
(Mac OS 10.6和iOS4.0)后,利用GCD(Grand Central Dispatch)
和ARC(Automatic Reference Counting)
实现单例。
+(SchoolManager *)sharedInstance
{
__strong static SchoolManager *sharedManager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[SchoolManager alloc] init];
});
return sharedManager;
} ```
>函数void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);其中第一个参数predicate,该参数是检查后面第二个参数所代表的代码块是否被调用的谓词,第二个参数则是在整个应用程序中只会被调用一次的代码块。dispach_once函数中的代码块只会被执行一次,而且还是线程安全的。
看到如下一篇文章,用宏实现(<https://gist.github.com/lukeredpath/1057420>):
//ExampleClass.m
@implementation MySharedThing
- (id)sharedInstance
{
DEFINE_SHARED_INSTANCE_USING_BLOCK(^{
return [[self alloc] init];
});
}
@end
GCDSingleton.h
define DEFINE_SHARED_INSTANCE_USING_BLOCK(block)
static dispatch_once_t pred = 0;
__strong static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = block();
});
return _sharedObject;