首页 > 代码库 > Objective-C中的单例模式
Objective-C中的单例模式
? ?单例模式算是设计模式中比较简单的一种吧,设计模式不是只针对某种编程语言,在C++, Java, PHP等其他OOP语言也有设计模式,笔者初接触设计模式是通过《漫谈设计模式》了解的。这本书中是用java写的,个人感觉拜读完这本书以后虽然有不理解的地方但还是收获蛮大的。上面提到依赖注入,控制翻转的时候,没大看懂,当学习到Strut,Spring, Hibernate的东西的时候才略懂略懂。不过在23种设计模式里面单例模式还是算比较好理解的, 那么在OC中又是怎么来表示单例模式的呢?下面会结合着lusashi的代码,理解一下OC中得单例模式。
? ?首先得了解什么是单例模式,用大白话说,单例模式就是在程序中这个类只对应着一个实例,这就是单例模式,单例模式一般用全局静态对象来实现。下面我们会建立一个生成单例的类SingletonClass,在实现文件中定义各种方法来实现我们的单例模式。
? ?1.单例模式一般用全局静态对象来实现,所以我们在SingletonClass.m中定义一个静态全局变量是少不了的
1 2 | //定义静态全局变量 static SingletonClass *single = nil; |
? ?2.上面的静态变量是定义在实现文件中的所以是私有的,要想获取该类的实例得有个getInstance方法来获取实例,在给静态变量分配内存空间之前首先要判断是否已经分配过啦,确保单例,如果分配过了就不分配了。
1 2 3 4 5 6 7 8 9 | //获取静态全局对象 +(id)getInstance { //如果没有生成对象,则为静态全局变量分配内存 if (single == nil) { single = [[SingletonClass alloc] init]; } return single; } |
? ?
? ?3.为了防止用户通过alloc和new来实例化对象,因此我们要对类方法allcoWithZone进行重写
1 2 3 4 5 6 7 8 | //防止通过alloc或者new来创建新的对象我们要重写allocWithZone +(id)allocWithZone:(NSZone *)zone { if (single == nil) { single = [[super allocWithZone:zone] init]; } return single; } |
? ?4.为了防止用户把单例进行深浅拷贝,我们需要重写copyWithZone方法和mutableCopyWithZone方法,在重写方法之前我们的单例类必须遵循协议NSCoping和NSMutableCoping协议
? ?遵循协议代码如下:
1 2 3 4 5 6 7 8 9 | @interface SingletonClass : NSObject<NSCopying, NSMutableCopying> //单例中获取单例对象的方法 +(id) getInstance; //单例测试方法 -( void ) singletonFunction; @end |
? ?重写copyWithZone方法
1 2 3 4 5 | //为了防止通过copy来创建新的实例我们要重写copyWithZone; -(id)copyWithZone:(NSZone *)zone { return self; } |
? ?重写mutableCopyWithZone方法
1 2 3 4 | -(id)mutableCopyWithZone:(NSZone *)zone { return self; } |
?5.防止用户把创建的单例dealloc,我们需要重写retainCount方法
1 2 3 4 5 | //重写retainCount方法,防止被dealloc,返回最大值 -(NSUInteger) retainCount { return NSUIntegerMax; } |
?6. 重写release,autorelease, retain方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //重写retain,引用计数不变 -(id) retain { return self; } //重写release -(oneway void ) release { } //重写autorelease -(id) autorelease { return self; } |
?至此我们的单例模式基本创建完毕,下面开始我们的测试吧;
?在main函数中的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //单例模式的测试 SingletonClass *single1 = [SingletonClass getInstance]; SingletonClass *single2 = [SingletonClass new ]; SingletonClass *single3 = [[SingletonClass alloc] init]; SingletonClass *single4 = [single1 copy]; SingletonClass *single5 = [single1 mutableCopy]; SingletonClass *single6 = [single1 retain]; [single1 release]; [single1 singletonFunction]; NSLog(@ "single_retainCount = %lu" , single1.retainCount); //输出地址 NSLog(@ "getInstance single1_P = %p" , single1); NSLog(@ "new single2_P = %p" , single2); NSLog(@ "allo single3_P = %p" , single3); NSLog(@ "copy single4_P = %p" , single4); NSLog(@ "mutableCopy single5_P = %p" , single5); NSLog(@ "retain single6_P = %p" , single6); |
? ?运行结果如下:
1 2 3 4 5 6 7 8 | 2014-08-07 16:04:44.207 Memory[20664:303] singleton Ps: 我是单例模式中得测试方法!! 2014-08-07 16:04:44.207 Memory[20664:303] single_retainCount = 18446744073709551615 2014-08-07 16:04:44.207 Memory[20664:303] getInstance single1_P = 0x100204690 2014-08-07 16:04:44.208 Memory[20664:303] new single2_P = 0x100204690 2014-08-07 16:04:44.208 Memory[20664:303] allo single3_P = 0x100204690 2014-08-07 16:04:44.208 Memory[20664:303] copy single4_P = 0x100204690 2014-08-07 16:04:44.209 Memory[20664:303] mutableCopy single5_P = 0x100204690 2014-08-07 16:04:44.209 Memory[20664:303] retain single6_P = 0x100204690 |
? ? ?单例的地址是不变的。