Objective-C中的单例模式

来源:互联网 发布:网盘搬家软件 编辑:程序博客网 时间:2024/04/30 21:40

单例模式算是设计模式中比较简单的一种吧,设计模式不是只针对某种编程语言,在C++, Java, PHP等其他OOP语言也有设计模式,笔者初接触设计模式是通过《漫谈设计模式》了解的。这本书中是用java写的,个人感觉拜读完这本书以后虽然有不理解的地方但还是收获蛮大的。上面提到依赖注入,控制翻转的时候,没大看懂,当学习到Strut,Spring, Hibernate的东西的时候才略懂略懂。不过在23种设计模式里面单例模式还是算比较好理解的, 那么在OC中又是怎么来表示单例模式的呢?下面会结合着lusashi的代码,理解一下OC中得单例模式。


首先得了解什么是单例模式,用大白话说,单例模式就是在程序中这个类只对应着一个实例,这就是单例模式,单例模式一般用全局静态对象来实现。下面我们会建立一个生成单例的类SingletonClass,在实现文件中定义各种方法来实现我们的单例模式。


  1. 单例模式一般用全局静态对象来实现,所以我们在SingletonClass.m中定义一个静态全局变量是少不了的


//定义静态全局变量

staticSingletonClass*single = nil;


2.上面的静态变量是定义在实现文件中的所以是私有的,要想获取该类的实例得有个getInstance方法来获取实例,在给静态变量分配内存空间之前首先要判断是否已经分配过啦,确保单例,如果分配过了就不分配了。


//获取静态全局对象

+(id)getInstance

{

//如果没有生成对象,则为静态全局变量分配内存

if(single == nil){

single = [[SingletonClassalloc] init];

}

returnsingle;

}


3.为了防止用户通过alloc和new来实例化对象,因此我们要对类方法allcoWithZone进行重写


//防止通过alloc或者new来创建新的对象我们要重写allocWithZone

+(id)allocWithZone:(NSZone*)zone

{

if(single == nil){

single = [[super allocWithZone:zone] init];

}

returnsingle;

}


4.为了防止用户把单例进行深浅拷贝,我们需要重写copyWithZone方法和mutableCopyWithZone方法,在重写方法之前我们的单例类必须遵循协议NSCoping和NSMutableCoping协议


遵循协议代码如下:


@interface SingletonClass : NSObject

//单例中获取单例对象的方法

+(id)getInstance;

//单例测试方法

-(void)singletonFunction;

@end

重写copyWithZone方法

//为了防止通过copy来创建新的实例我们要重写copyWithZone;

-(id)copyWithZone:(NSZone*)zone

{

returnself;

}

重写mutableCopyWithZone方法

-(id)mutableCopyWithZone:(NSZone*)zone

{

returnself;

}


5.防止用户把创建的单例dealloc,我们需要重写retainCount方法


//重写retainCount方法,防止被dealloc,返回最大值

-(NSUInteger)retainCount

{

returnNSUIntegerMax;

}


6. 重写release,autorelease, retain方法


//重写retain,引用计数不变

-(id)retain

{

returnself;

}

//重写release

-(onewayvoid)release

{

}

//重写autorelease

-(id)autorelease

{

returnself;

}


至此我们的单例模式基本创建完毕,下面开始我们的测试吧;

在main函数中的代码如下:


//单例模式的测试

SingletonClass*single1 = [SingletonClassgetInstance];

SingletonClass*single2 = [SingletonClassnew];

SingletonClass*single3 = [[SingletonClassalloc] init];

SingletonClass*single4 = [single1copy];

SingletonClass*single5 = [single1mutableCopy];

SingletonClass*single6 = [single1retain];

[single1release];

[single1singletonFunction];

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);


运行结果如下:


2014-08-0716:04:44.207Memory[20664:303] singletonPs:我是单例模式中得测试方法!!

2014-08-0716:04:44.207Memory[20664:303] single_retainCount = 18446744073709551615

2014-08-0716:04:44.207Memory[20664:303] getInstance single1_P = 0x100204690

2014-08-0716:04:44.208Memory[20664:303]new single2_P = 0x100204690

2014-08-0716:04:44.208Memory[20664:303] alloCsingle3_P = 0x100204690

2014-08-0716:04:44.208Memory[20664:303] copy single4_P = 0x100204690

2014-08-0716:04:44.209Memory[20664:303] mutableCopy single5_P = 0x100204690

2014-08-0716:04:44.209Memory[20664:303] retain single6_P = 0x100204690


单例的地址是不变的。


上面是在非ARC模式下得单例模式,那么在ARC模式下我们应如何实现我们的单例模式呢,我们下面就会给出ARC下的单例模式,用下面的方法,因没有重写alloc,copy等方法,通过alloc还是可以给该对象分配一个新对象的,上面是线程不安全的,下面是线程安全的:


+(id)sharedSingleton{

staticMySingleton *sharedSingleton = nil;

staticdispatch_once_tonceToken;

dispatch_once(&onceToken, ^{

sharedSingleton = [[selfalloc]init];

});

returnsharedSingleton;

}

0 0
原创粉丝点击