单例设计模式是在开发中经常可以看到的一种设计模式,不管是在 Cocoa Touch框架还是我们自己的业务逻辑中都可以看到它的身影。
1、首先解答一个问题,什么是单例设计模式呢?
它可以保证在我们的 App 里面某个类创建出来的对象有且仅有一个。
2、其次为什么要使用单例设计模式,直接创建对象不行么?
1)这个要从单例设计模式的作用说起,在手持设备当中,内存的使用很多情况下都是要斤斤计较,单例设计模式可以保证在我们的 App 里面某个类创建出来的对象有且仅有一个,那么它的一个作用就是可以节省内存开销。
2)如果我们的 App 有一份数据,整个 App 到处都有可能使用到这份数据(比如登录的用户信息),只需要使用同一份数据(保证大家访问的数据是相同的,一致的)。
3)工具类一般都可以设计成单例设计模式。
3、OC如何用宏定义实现单例设计模式(ARC 模式)
1)// .h文件的实现
系统提供的单例设计模式方法都是以shared 开头,那么我们的写法就遵循系统的命名规范,## 就是一个连接符,会将 methodName变量的值拼接在shared后面形成一个方法名,每行末尾的“\”也是 C语言一个连接符。
#define SingletonH(methodName) + (instancetype)shared##methodName;
2)// .m文件的实现
实现单例就是要保证类的实例只创建一次,后面及时调用 alloc/init/new/copy等方法的时候也是返回第一次创建的对象实例,那么就需要覆写以下方法
+ (id)allocWithZone:(struct _NSZone *)zone ;
- (id)init ;
+ (id)mutableCopyWithZone:(struct _NSZone *)zone;
不过还需要加上我们自己的创建方法
+ (instancetype)shared##methodName
为了保证更加安全地创建我们的类实例对象,我们使用 GDC的一个特性来保证实例的生成安全,它能保证我们的创建对象实例代码有且仅有被执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ });
3)最后贴上我们的.m 文件
#define SingletonM(methodName) \
static id _instace = nil; \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
if (_instace == nil) { \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super allocWithZone:zone]; \
}); \
} \
return _instace; \
} \
\
- (id)init \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super init]; \
}); \
return _instace; \
} \
\
+ (instancetype)shared##methodName \
{ \
return [[self alloc] init]; \
} \
+ (id)copyWithZone:(struct _NSZone *)zone \
{ \
return _instace; \
} \
\
+ (id)mutableCopyWithZone:(struct _NSZone *)zone \
{ \
return _instace; \
}
@interface UserTool : NSObject
SingletonH(UserTool)
@end
@implementation UserTool
SingletonM(UserTool)
@end
总结:用宏定义实现单例设计模式确实快捷,但是也有一定的隐患,在编译过程中,编译器会查找和替换“SingletonH”和“SingletonM”,所以在命名其他变量或者方法的时候需要留心一下,以免多出不必要的麻烦。