(一)什么是单例模式(Singleton)
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点 *最初的定义是在<设计模式>(Addison-Wesley)中
解读
1>在数学与逻辑学中,Singleton的定义是:"有且只有一个元素的集合".
2>在程序中,无论以什么方式创建对象,总是放回第一次创建的对象
(二)何时使用单例模式
类只能有一个实例,并且必须从一个为人熟知的访问点对其进行访问,比如工厂方法
避免重复生成同一对象浪费内存空间
(三)实现单例模式的思想-拦截创建对象的方法,在调用创建对象的方法时,总是返回第一次创建的对象
(四)在iOS中实现单例模式的方法
1>通过GCD中的once函数来进行实现
#import <Foundation/Foundation.h> @interface ZDZPerson : NSObject + (instancetype)sharedPerson;
@end
ZDZPerson.h
#import "ZDZPerson.h" @interface ZDZPerson () <NSCopying> @end @implementation ZDZPerson //创建一个全局变量(目的是在整个生命周期都可以访问到)
static id _person; //调用alloc方法或其他生成对象的方法时会默认调用allocWithZone方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t tokenOnce;
dispatch_once(&tokenOnce, ^{
_person = [super allocWithZone:zone];
});
return _person;
} //实现此方法避免因copy对象时 产生新的对象
- (id)copyWithZone:(NSZone *)zone {
return _person;
} //自定义sharedPerson方法 返回对象
+ (instancetype)sharedPerson {
static dispatch_once_t tokenOnce;
dispatch_once(&tokenOnce, ^{
_person = [[self alloc] init];
});
return _person;
} @end
ZDZPerson.m
2>通过为线程加锁的方式实现
#import <Foundation/Foundation.h> @interface ZDZAnimal : NSObject
+ (instancetype)sharedAnimal;
@end
ZDZAnimal.h
#import "ZDZAnimal.h" @implementation ZDZAnimal
static id _animal; //调用alloc方法或其他生成对象的方法时会默认调用allocWithZone方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
@synchronized(self) {
if (_animal == nil) {
_animal = [super allocWithZone:zone];
}
}
return _animal;
} //实现此方法避免因copy对象时 产生新的对象
- (id)copyWithZone:(NSZone *)zone {
return _animal;
} //自定义sharedPerson方法 返回对象
+ (instancetype)sharedAnimal {
@synchronized(self) {
_animal = [[self alloc] init];
}
return _animal;
}
@end
ZDZAnimal.m
(五)实现单例类代码的复用:通过#define来实现单例代码的复用
1>代码解读
#define kZDZSingletonH(name) + (instancetype)shared##name; 可以通过此方式动态设置函数名
扩展:
#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #xx##y表示什么?表示x连接y,举例说:
int n = Conn(123,456); 结果就是n=123456;
char* str = Conn("asdf", "adf")结果就是 str = "asdfadf";
怎么样,很神奇吧再来看#@x,其实就是给x加上单引号,结果返回是一个const char。举例说:
char a = ToChar(1);结果就是a='1';
做个越界试验char a = ToChar(123);结果是a='3';
但是如果你的参数超过四个字符,编译器就给给你报错了!error C2015: too many characters in constant :P最后看看#x,估计你也明白了,他是给x加双引号
char* str = ToString(123132);就成了str="123132";注:转载他人
1>工具类代码
#define kZDZSingletonH(name) + (instancetype)shared##name; #define kZDZSingletonM(name)\
static id _instance;\
\
+ (instancetype)allocWithZone:(struct _NSZone *)zone {\
static dispatch_once_t tokenOnce;\
dispatch_once(&tokenOnce, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
\
- (id)copyWithZone:(NSZone *)zone {\
return _instance;\
}\
\
+ (instancetype)shared##name {\
static dispatch_once_t tokenOnce;\
dispatch_once(&tokenOnce, ^{\
_instance = [[self alloc] init];\
});\
return _instance;\
}
ZDZSingleton.h
2>使用方法
#import <Foundation/Foundation.h>
#import "ZDZSingleton.h" @interface ZDZComputer : NSObject kZDZSingletonH(Computer) @end
ZDZComputer.h
#import "ZDZComputer.h" @implementation ZDZComputer kZDZSingletonM(Computer) @end
ZDZComputer.m