跳转至

单例模式

单例模式是一种创建对象的设计模式,保证一个类只有一个实例,并且提供一个全局的访问点。

饿汉式单例模式指的是在程序启动时就创建实例,以确保在任何时候都只有一个实例存在。这种方式简单、线程安全,但可能会浪费系统资源,因为实例在程序启动时就被创建出来,即使在程序运行期间不需要它也会一直存在。

懒汉式单例模式指的是在需要使用实例时才创建,以避免浪费系统资源。这种方式需要在多线程环境下进行额外的同步措施,以保证线程安全性。

懒汉式单例模式有两种实现方式:双重检查锁(Double Checked Locking)和静态内部类(Static Inner Class)。

双重检查锁方式在第一次调用时才进行实例化,在多线程环境下保证线程安全,同时又避免了每次获取实例都需要同步的性能问题。但是这种方式实现较为复杂,容易出现空指针异常等问题。

静态内部类方式通过定义一个私有静态内部类来实现懒加载,这个内部类只有在需要使用时才会被加载,从而实现了懒加载的效果。这种方式具有良好的线程安全性和较好的性能,是比较常用的一种单例模式实现方式。

为什么使用单例模式

在应用系统开发中,我们常常有以下需求:

  • 在多个线程之间,比如初始化一次socket资源;比如servlet环境,共享同一个资源或者操作同一个对象
  • 在整个程序空间使用全局变量,共享资源
  • 大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。

因为Singleton模式可以保证为一个类只生成唯一的实例对象,所以这些情况,Singleton模式就派上用场了。

重点:多线程 加锁 两次判断

如何保证一个类只有一个实例:

  1. 用一个私有的静态的数据成员 创建一个对象 保证只有一个对象。

  2. 构造函数做成私有的。

  3. 拷贝构造函数做成私有的。

  4. 通过一个共有的方法去使用上面的方法,用指针返回对象(静态的唯一的对象)的地址。

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中allocWithZonecopyWithZone方法要重写。

在对象创建的时候,无论是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
}