单例实现代码(懒汉式)

单例实现代码(懒汉式)

.h文件

1 #import <Foundation/Foundation.h>
2 
3 @interface MusicLab : NSObject
4 
5 //封装类方法
6 +(instancetype)shareMusicLab;
7 
8 @end

.m文件

 1 #import "MusicLab.h"
 2 
 3 @interface MusicLab()
 4 
 5 //类延展中创建的实例变量和属性,都不能被其他类中创建的该类对象访问,必须放在.h文件中
 6 
 7 @end
 8 
 9 @implementation MusicLab
10 
11 
12 //搞个全局变量来保存MusicLab类创建的唯一对象. 必须加static,否则别的.m文件可以修改它
13 static MusicLab *musicObj;
14 
15 
16 //此方法也判断两次,为了防止某个SB不使用单例shareMusicLab方法,直接调用[[MusicLab alloc]init];
17 //类调用alloc方法,其实是在调用allocWithZone方法
18 +(instancetype)allocWithZone:(struct _NSZone *)zone{
19     
20     if (musicObj == nil) { //此判定是为了每次调用alloc方法时都要加锁
21         @synchronized(self){
22             NSLog(@"已经加锁");
23             if (!musicObj) { //防止多个线程进来判定musicObj=nil,在此之前加锁,进不来。
24                 musicObj = [super allocWithZone:zone]; //该代码执行完,musicObj就不在是空nil了,
25             }
26         }
27 
28     }
29 
30     return musicObj;
31 }
32 
33 
34 +(instancetype)shareMusicLab{
35     
36     //假设2个线程A.B同时进来,判定musicObj的确是nil,
37     if(musicObj == nil){ //线程A,B来到这里,但是此线程加锁。假设A加锁后进入,B在外面等待
38         
39         @synchronized(self){//线程A加锁后进入
40             
41             if (musicObj == nil) {//线程A判定为空,继续执行
42                 
43                 musicObj = [[self alloc]init];//线程A创建musicObj对象
44             }
45         }//线程A出门,musicObj已经有值了。线程B继续上锁进入,但是此时if (musicObj == nil)不成立,只得返回
46     }
47     
48     return musicObj;
49     
50 }
51 
52 -(id)copyWithZone:(NSZone *)zone{
53 
54     return musicObj;
55 }
56 
57 
58 
59 //NSLog遇到%@就会调用该方法,将该方法返回的字符串替代%@后面的值。
60 //- (NSString *)description{
61 //    return [NSString stringWithFormat:@"地址:%p",self];
62 //}
63 
64 @end

 

ViewController.m文件

 1 //单例: 确保一个类无论调用它多少次,用它创建多少个对象,其创建的都是同一个对象,这些对象调用它内部的属性,得到的都是相同的值
 2 
 3 #import "ViewController.h"
 4 #import "MusicLab.h"
 5 
 6 @interface ViewController ()
 7 
 8 @end
 9 
10 @implementation ViewController
11 
12 - (void)viewDidLoad {
13     [super viewDidLoad];
14     
15     //因为每次创建对象都要调用alloc分配内存,故单例需从alloc方法下手,调用alloc方法,其本质又是调用
16     MusicLab *musicLab = [[MusicLab alloc]init];
17     MusicLab *musicLab1 = [[MusicLab alloc]init]; 
18     MusicLab *musicLab2 = [[MusicLab alloc]init]; //修改代码后只有第一次加锁,后面调用都不加锁,故加锁方法只被打印一次
19     MusicLab *musicLab3 = [MusicLab shareMusicLab];
20     MusicLab *musicLab4 = [musicLab2 copy]; //copy方法会调用copyWithZone;
21     
22     NSLog(@"\n musicLab地址: %p\n musicLab1地址:%p",musicLab,musicLab1);
23     NSLog(@"\n musicLab3地址:%p\n musicLab4地址:%p",musicLab3,musicLab4);
24     
25 //    NSLog(@"\n musicLab实例变量地址: %p\n musicLab1实例变量地址:%p",musicLab.musics,musicLab1.musics); //同一个类的不同对象调用musics属性返回相同的地址,单例已实现
26     
27 }

 

posted @ 2015-11-17 21:25  stevenwuzheng  阅读(587)  评论(0编辑  收藏  举报