单例 singleton
一、单例模式
特点:单例模式的类必须保证始终只有一个实例存在。
场景:在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次),应该让这个类创建出来的对象永远只有一个。
二、单例类的构建
1:为你的单例类声明一个静态的实例,并且初始化它的值为nil。
2:在获取实例的方法中,只有在静态实例为nil的时候,产生一个你的类的实例,这个实例通常被称为共享的实例。
3:重写allocWithZone 方法,用于确定:不能够使用其他的方法来创建我们不得实例,限制用户只能通过获取实例的方法得到这个类的实例。所以,我们在allocWithZone方法中直接返回共享的类实例。
4:实现基本的协议方法 copyWithZone、release、retain、retainCount 和 autorelease,用于保证单例具有一个正确的状态。(MRC下)非arc
5:在init方法中初始化一些东西
三、多线程下的单例
使用@sychronized(){}指令
四、栗子
#import <Foundation/Foundation.h> //图片管理类 //单例类 @interface ZYImageManager : NSObject + (ZYImageManager *)shareImageManager; - (void)test; @end
#import "ZYImageManager.h" /* 1、声明静态实例 并初始化值为nil 2、声明静态方法 方法中判断如果实例为nil就创建 3、重写allocWithZone方法 杜绝创建新的实例 4、重写copyWithZone方法 防止对象copy 5、重写引用计数相关东西 推荐 6、init方法 初始化一些东西 7、因为创建本类实例时 使用了alloc alloc会调用allocWithZone 然而allocWithZone又被本类重写了 所以应改为[super allocWithZone:NULL] 8、处理多线程下的线程同步 */ //栈、堆、全局变量区(静态区)、方法区、常量区 static ZYImageManager *singletonInstance = nil; static int count = 10; // count 的作用是证明这个类只创建了一次 @implementation ZYImageManager + (ZYImageManager *)shareImageManager { //@synchronized(self) 管理线程:Objective-C在应用程序中支持多任务。这意味着可能有两个线程同时试图修改同一个对象。有一个办法可以解决这个情况。为了防止多个线程同时执行同一个代码块,OC提供了@synchronized()指令。 //使用@synchronized()指令可以锁住在线程中执行的某一个代码块。使用代码块的其他线程,将被阻塞,这也就意味着,他们将在@synchronized()代码块的最后一条语句执行结束后才能继续执行。一般在公用变量的时候使用,如单例模式或者操作类的static变量中使用。 @synchronized(self) { if (singletonInstance == nil) { //调用父类方法开辟空间 参数无用 singletonInstance = [[super allocWithZone:NULL] init]; //在NSObject 这个类的官方文档里面,allocWithZone方法介绍说,该方法的参数是被忽略的,正确的做法是传nil或者NULL参数给它。而这个方法之所以存在,是历史遗留原因。就是你不用传参就会给你开辟空间 //而为什么不用[[ super alloc] init]那 因为这样他还会调用子类的allocwithzoon count++; } } return singletonInstance; } //重写初始化方法 初始化一些需要初始化的东西 - (id)init { self = [super init]; if (self) { } return self; } //分配内存 //因为alloc会调用此方法 所以应重写防止其再创建对象 + (id)allocWithZone:(struct _NSZone *)zone { return singletonInstance; } //copy时会调用此方法 + (id)copyWithZone:(struct _NSZone *)zone { return singletonInstance; } //重写一下跟引用计数有关的东西 推荐 - (id)retain { return self; } //重写release以及autorelease - (oneway void)release { } - (id)autorelease { return self; } //返回1可以 如下亦可 - (NSUInteger)retainCount { return NSUIntegerMax; } - (void)test { NSLog(@"%d", count); } @end
#import "ZYAppDelegate.h" #import "ZYImageManager.h" @implementation ZYAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; //测试单例 [[ZYImageManager shareImageManager] test]; ZYImageManager *imageManager = [ZYImageManager shareImageManager]; [imageManager test]; ZYImageManager *imageManager2 = [[ZYImageManager alloc] init]; //查看单例内存地址 内存地址一样 没什么好说的 NSLog(@"%@__%@", imageManager2, imageManager); [imageManager2 test]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; } @end