单例模式¶
单例模式是一种创建对象的设计模式,保证一个类只有一个实例,并且提供一个全局的访问点。
饿汉式单例模式指的是在程序启动时就创建实例,以确保在任何时候都只有一个实例存在。这种方式简单、线程安全,但可能会浪费系统资源,因为实例在程序启动时就被创建出来,即使在程序运行期间不需要它也会一直存在。
懒汉式单例模式指的是在需要使用实例时才创建,以避免浪费系统资源。这种方式需要在多线程环境下进行额外的同步措施,以保证线程安全性。
懒汉式单例模式有两种实现方式:双重检查锁(Double Checked Locking)和静态内部类(Static Inner Class)。
双重检查锁方式在第一次调用时才进行实例化,在多线程环境下保证线程安全,同时又避免了每次获取实例都需要同步的性能问题。但是这种方式实现较为复杂,容易出现空指针异常等问题。
静态内部类方式通过定义一个私有静态内部类来实现懒加载,这个内部类只有在需要使用时才会被加载,从而实现了懒加载的效果。这种方式具有良好的线程安全性和较好的性能,是比较常用的一种单例模式实现方式。
为什么使用单例模式¶
在应用系统开发中,我们常常有以下需求:
- 在多个线程之间,比如初始化一次socket资源;比如servlet环境,共享同一个资源或者操作同一个对象
- 在整个程序空间使用全局变量,共享资源
- 大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。
因为Singleton模式可以保证为一个类只生成唯一的实例对象,所以这些情况,Singleton模式就派上用场了。
重点:多线程 加锁 两次判断
如何保证一个类只有一个实例:
-
用一个私有的静态的数据成员 创建一个对象 保证只有一个对象。
-
构造函数做成私有的。
-
拷贝构造函数做成私有的。
-
通过一个共有的方法去使用上面的方法,用指针返回对象(静态的唯一的对象)的地址。
class Egg
{
static Egg e;
int i;
Egg(int ii):i(ii){}//构造函数做成私有的
Egg(const Egg&);//把拷贝构造函数做成私有的,不允许使用
public:
static Egg* instance() {return &e;}
int val() const { return i;}
};
Egg Egg::e(47);
void test777()
{
// Egg e;
// Egg e2;
Egg* e = Egg::instance();
Egg* e2 = Egg::instance();
//下面两种其实也是拷贝,所以需要把拷贝构造函数做成私有的,不允许使用。
// Egg e3 = *Egg::instance();//获取地址
// Egg e4(*Egg::instance());//拷贝 复制
}
Objective-C¶
iOS中allocWithZone
和copyWithZone
方法要重写。
在对象创建的时候,无论是alloc还是new,都会调用到 allocWithZone方法。
在通过拷贝的时候创建对象时,会调用到-(id)copyWithZone:(NSZone **)zone
,-(id)mutableCopyWithZone:(NSZone* *)zone
方法。
因此重写这些方法,让创建的对象唯一。
static id instance = nil;
+ (instancetype)shareInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
@synchronized (self) {
if (instance == nil) {
instance = [super allocWithZone:zone];
return instance;
}
return instance;
}
}
- (id)copyWithZone:(NSZone *)zone
{
@synchronized (self) {
if (instance == nil) {
instance = [[SingletonManager allocWithZone:zone]init];
return instance;
}
return instance;
}
}
Dart¶
可以使用Dart的静态变量和工厂构造函数来实现单例模式。
class Singleton {
// 私有构造函数,只能在类的内部被调用。
Singleton._privateConstructor();
// _instance:静态变量,通过私有构造函数创建的单例对象。
static final Singleton _instance = Singleton._privateConstructor();
// 工厂构造函数,每次调用时都返回同一个单例对象。
factory Singleton() {
return _instance;
}
// 可以在这里添加实例变量和方法
}
使用这个单例对象:
void main() {
Singleton singleton1 = Singleton();
Singleton singleton2 = Singleton();
print(identical(singleton1, singleton2)); // 输出:true
}