单例模式,单件模式
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
一个类只允许创建一个对象(或者实例),那么这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。
单例模式.jpg熟悉C++或Java的童鞋都知道单例模式有饿汉式和懒汉式两种。而OC是不支持饿汉式,因为静态常量不是编译时常量。
一般常用的都是懒汉式,除了多线程外还要考虑的new、copy等情况
代码示例
方案一:宏定义
single.h
#define SingleH(name) + (instancetype)shared##name;
#if __has_feature(objc_arc)
//ARC
#define SingleM(name) static id _instance;\
+ (instancetype)allocWithZone:(struct _NSZone *)zone {\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
\
+ (instancetype)shared##name {\
return [[self alloc]init];\
}\
\
- (id)copyWithZone:(NSZone *)zone {\
return _instance;\
}\
\
- (id)mutableCopyWithZone:(NSZone *)zone {\
return _instance;\
}
#else
//MRC
#define SingleM(name) static id _instance;\
+ (instancetype)allocWithZone:(struct _NSZone *)zone {\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
\
+ (instancetype)shared##name {\
return [[self alloc]init];\
}\
\
- (id)copyWithZone:(NSZone *)zone {\
return _instance;\
}\
\
- (id)mutableCopyWithZone:(NSZone *)zone {\
return _instance;\
}\
\
- (oneway void)release {\
\
}\
\
- (instancetype)retain {\
return _instance;\
}\
\
- (NSUInteger)retainCount {\
return MAXFLOAT;\
}\
\
- (instancetype)autorelease {\
return _instance;\
}
#endif
main.m
#import <Foundation/Foundation.h>
#import "Single.h"
@interface YQTest : NSObject
SingleH(Tools)
@end
@implementation YQTest
SingleM(Tools)
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
YQTest *s1 = [YQTest sharedTools];
YQTest *s2 = [YQTest sharedTools];
NSLog(@"%p-%p", s1, s2);
//0x1006233e0-0x1006233e0
}
return 0;
}
方案二:声明禁用new、copy等方法
#import <Foundation/Foundation.h>
@interface YQNetworkTools : NSObject
+ (instancetype)shared;
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;
- (id)copy UNAVAILABLE_ATTRIBUTE;
- (id)mutableCopy UNAVAILABLE_ATTRIBUTE;
@end
@implementation YQNetworkTools
static YQNetworkTools *sharedInstance = nil;
+ (instancetype)shared {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc]init];
});
return sharedInstance;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
YQNetworkTools *t1 = [YQNetworkTools shared];
YQNetworkTools *t2 = [YQNetworkTools shared];
NSLog(@"%p-%p", t1, t2);
//0x1007179b0-0x1007179b0
//YQNetworkTools *t3 = [[YQNetworkTools alloc] init];
//YQNetworkTools *t4 = [YQNetworkTools new];
//YQNetworkTools *t5 = [t1 copy];
//YQNetworkTools *t6 = [t1 mutableCopy];
}
return 0;
}
用处
从业务概念上,有些数据在系统中只应该保存一份,就比较适合设计为单例类,表示全局唯一类。比如系统的配置信息类,工具类等。
iOS系统提供了很多单例的类UIApplication
、NSUserDefaults
、NSFileManager
、NSURLCache
、NSNull
等等
优点
只会实例化一次,如果有问题能快速定位。只有一个对象,节省系统内存资源,提高运行效率。
缺点
- 单例对OOP特性的支持不友好
违背了基于接口而非实现编程 - 不易扩展或重写
需求变更,开发中遇到问题 - 闲置消耗内存资源(一直存在)
题外话
iOS也可以实现多例模式
,想要了解更多代理应用的童鞋可以自行学习了解一下。
网友评论