定义:
单例模式使用场景,必须一个类只有一个实例,并且提供一个访问它的全局访问点。
单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
从具体实现角度来说,就是以下三点:一是单例模式的类只提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象
在 Cocoa Touch中 比较代表的就是 UIApplication ---[UIApplication sharedApplication]。
下面我们来思考几个问题
1、我们为什么要用实例对象而不是类对象?
OC的类对象可以接受消息,也可以在其他对象中调用,而且runtime确保类在application生命周期内只初始化一次。
答案是:因为增加维护成本。(已经存在一个类,你想写个子类去实现同样的事情。首先使用的是类方法调用,那么你得替换所有的方法调用类名称)。
注意我们应该尽量避免硬编码类名,这样增加了将来维护的难度
解决方法:使用一个全局变量 存储使用的指针。
2、 那么直接使用全局变量的指针 是不是就完美了呢?
答案是:否。静态的全局变量,和对象的实例变量 比起来维护性太差。不具有面向对象的可以继承的能力。方法和变量也不具有多态的好处。
严谨的单例的创建:
static Singleton *_sharedSingleton = nil;
@implementation Singleton
- (instancetype)init {
[NSException raise:@"SingletonPattern"
format:@"Cannot instantiate singleton using init method, sharedInstance must be used."];
return nil;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
if (self != [Singleton class]) {
[NSException raise:@"SingletonPattern"
format:@"Cannot use sharedInstance method from subclass."];
}
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedSingleton = [[Singleton alloc] initInstance];
});
return _sharedSingleton;
}
+ (instancetype)new {
return [self alloc];
}
- (instancetype)copyWithZone:(NSZone *)zone {
return _sharedSingleton;
}
- (instancetype)mutableCopyWithZone:(NSZone *)zone {
return [self copyWithZone:zone];
}
+ (Singleton *)sharedInstance {
if (self != [Singleton class]) {
[NSException raise:@"SingletonPattern"
format:@"Cannot use sharedInstance method from subclass."];
}
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedSingleton = [[Singleton alloc] initInstance];
});
return _sharedSingleton;
}
#pragma mark - private method
- (instancetype)initInstance {
return [super init];
}
@end
最后:
只有当一个类表示真正应该存在一次时,才使它成为单例。有些时候,最初看起来符合这个标准的东西将不再适合应用程序的发展。例如,有多个类型需求,或者是不是生命周期只存在一次。在这种情况下单例方法不再适用。通常,我们会使用manger的管理方式。例如NSFileManager。接下来介绍manger管理方式。
网友评论