单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
单例内部的属性一旦赋值,只要程序不关,在整个项目的任何地方再次实例,内部的属性值不会变,使用起来非常方便;
下面我们来写一个稍微全面一点的单例
首先在项目中建一个继承自NSObject的类,名为DanLi,将作为单例使用,和一个工程的主根类MainViewController
1.在DanLi.h中简单的写入一个属性和一个实例对象的工厂方法,代码示例如下:
#import <Foundation/Foundation.h>
@interface DanLi : NSObject
@property (strong,nonatomic) NSString *danLiStr;
+(DanLi *)getInstance;
@end
2.在DanLi.m中首先创建一个全局的静态实例,然后实现工厂方法,代码如下:
#import "DanLi.h"
//创建一个全局实例,并实例化为nil
static DanLi *danLi=nil;
@implementation DanLi
//实现工厂方法,然后返回单一一个变量
+(DanLi *)getInstance
{
if (danLi==nil)
{
danLi=[[DanLi alloc]init];
}
return danLi;
}
其实到了这里基本已经可以很好地使用了,但是为了安全和严谨,要做一些细节处理在DanLi.m中加入以下几个方法的重定义:
//需要重写此方法,防止通过alloc和new来创建新的实例
+(id)allocWithZone:(struct _NSZone *)zone
{
if (danLi==nil)
{
danLi=[[super allocWithZone:zone] init];
}
return danLi;
}
//防止通过拷贝创建对象
-(id)copy
{
return self;
}
-(id)mutableCopy
{
return self;
}
这样在ARC环境下就基本大功告成了,可以随意的使用了,但是,如果是在MRC的环境下,最好还要在DanLi.m中实现以下方法的重定义
//重写此方法,防止被dealloc,此方法中返回最大值
-(NSUInteger)retainCount
{
return NSUIntegerMax;
}
//因为是单例,所以引用计数和释放都没有意义,所以需要重写以下方法
-(id)retain
{
return self;
}
-(oneway void)release
{
}
-(id)autorelease
{
return self;
}
然后回到我们的主页面
MainViewController去调用测试,首先导入DanLi.h
在MainViewController.m中就可以使用单例了(在整个项目中都可以随便调用),测试代码如下:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
DanLi *danLi=[DanLi getInstance];
danLi.danLiStr=@"xiaowei";
DanLi *danLif1=[[DanLi alloc]init];
NSLog(@"one==%@",danLif1.danLiStr);
DanLi *danLif4=[DanLi new];
NSLog(@"four==%@",danLif4.danLiStr);
DanLi *danLif2=[danLi copy];
NSLog(@"two==%@",danLif2.danLiStr);
DanLi *danLif3=[danLi mutableCopy];
NSLog(@"three==%@",danLif3.danLiStr);
}
因为我是用的ARC,所以简单测试这几个方法,但因结果如下:
2015-03-12 16:56:20.694 单例[4710:607] one==xiaowei
2015-03-12 16:56:20.695 单例[4710:607] four==xiaowei
2015-03-12 16:56:20.696 单例[4710:607] two==xiaowei
2015-03-12 16:56:20.696 单例[4710:607] three==xiaowei