1、单例模式的定义
单例模式确保一个类只有一个实例,并提供一个全局访问点。
2、使用场景
我们希望这个类在整个应用程序中,只有一个对象实例,并且提供一个全局访问接口。单例模式常常被用来管理共享的资源,例如,注册表信息,数据库连接或线程池等。对于全局共享的资源的访问,使用单例可以避免资源访问时数据的不一致问题。
3、单例模式的实现
1)单例模式在Java语言中的实现
对于Java的实现可以简单的概括为单例类没有公开的构造方法,外界不能自行实例化一个对象,只能通过通过这个单例类提供的静态接口方法获得该单例类的实例(单例类的实例化是在该类的内部完成的)。
这里给出两种实现。
其一:紧急加载型(饿汉式)
//在类初始化时,已经实例化对象
public class Singleton {
private Singleton() {}
private static final Singleton singleton = new Singleton();
public static Singleton getInstance() {
return singleton;
}
}
其二:延迟加载型(懒汉式)
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
这两种方法都能保证线程安全。饿汉式是在类创建的同时就已经创建好一个静态的对象可供使用,以后不再改变,所以是线程安全的。懒汉式使用了同步锁来保证线程安全,并且使用了双重检查加锁来减少同步的次数。
2)单例模式在Objective-C语言中的实现
先看一下苹果给的方案
Singleton
Singletons provide a globally accessible, shared instance of an object. You can create your own singletons as a way to provide a unified access point to a resource or service that’s shared across an app, such as an audio channel to play sound effects or a network manager to make HTTP requests.
In Objective-C, you can ensure that only one instance of a singleton object is created by wrapping its initialization in a call the dispatch_once function, which executes a block once and only once for the lifetime of an app:
+ (instancetype)sharedInstance {
static id _sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
In Swift, you can simply use a static type property, which is guaranteed to be lazily initialized only once, even when accessed across multiple threads simultaneously:
class Singleton {
static let sharedInstance = Singleton()
}
If you need to perform additional setup beyond initialization, you can assign the result of the invocation of a closure to the global constant:
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
可以看出苹果的实现并不是一种严格的单例模式。如果通过[SomeClass alloc] init]
和 [SomeClass sharedInstance]
的方式去获取对象,得到的就是不同的对象。如果你一直使用sharedInstance
方法去获取对象的话,那么得到的就是同一个对象。例如系统的NSFileManager类就是这种情况。在实际的开发中,我们可能也使用这种简洁的方式。
对于Objective-C来说,实现一个“严格的单例”可能稍微复杂一些(需要重写的方法较多),不像Java或C++那样提供了很好的机制来实现这一模式。在ARC模式下,我们可以这样来实现:
+ (instancetype)shareInstance {
return [[self alloc] init];
}
static Singleton *_instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
// 由于alloc方法内部会调用allocWithZone: 所以我们只需要保证在该方法只创建一个对象即可
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
- (id)copyWithZone:(NSZone *)zone {
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}
对于MRC来说,我们还要考虑引用计数内存模型,这个时候我们要重写于内存管理相关的方法。
+ (instancetype)shareInstance {
return [[self alloc] init];
}
static Singleton *_instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
// 由于alloc方法内部会调用allocWithZone: 所以我们只需要保证在该方法只创建一个对象即可
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
- (id)copyWithZone:(NSZone *)zone {
// 因为copy方法必须通过实例对象调用, 所以可以直接返回_instance
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}
- (oneway void)release {
}
- (instancetype)retain {
return _instance;
}
- (NSUInteger)retainCount {
return MAXFLOAT;
}