剑指02:题2-实现Singleton模式

105 阅读2分钟

题目

设计一个类,我们只能生成该类的一个实例。

思考

只能生成一个实例的类,是实现了 Singleton(单例)模式的类型,是考查了设计模式相关的问题

不好的解法1:只适用于单线程环境

由于要求只能生成一个实例,因此必须把构造函数设为私有函数,以禁止他人创建实例。

解法1:可以定义一个静态的实例,在需要的时候创建该实例。

不好的解法2:虽然在多线程环境中能工作,但效率不高

解法1中,单线程虽然能工作,但是在多线程下就有问题:如果两个线程同时运行到判断 instantce 是否为 null 的 if 语句,并且 instantce 的确没有创建时,那么两个线程都会创建一个实例,此时就不满足单例模式的要求。

为了解决该问题,需要加上一个同步锁。

解法2:加一个同步锁

加锁是一个非常耗时的操作,在没有必要的情况下,应该尽量避免。

可行的解法:加同步锁前后两次判断实例是否已存在

只是在实例还没有创建之前需要加锁操作,以保证只有一个线程创建出实例。当实例创建出来后,就不需要执行加锁操作。

解法3:

伪代码
if(instance == null){
    加锁{
        if(instance == null){
            instance = xxxx(); // 创建实例
        }
    }
}

通过2次 if 判断来提高效率。

但是代码实现较为复杂,易出错。

强烈推荐的解法1:利用静态构造函数

oc 语法中有一个函数能够确保只调用一次

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"只执行一次");
    });

强烈推荐的解法2:实现按需创建实例

某些编程语言的一些函数的调用时机不是由程序员控制的,可能导致在编译时触发,而不是在真正调用时触发,所以,需要做到按需加载,不会过早创建实例,从而降低内存的使用效率。

考察点:

  • 单例模式
  • 基础语法的理解
  • 多线程