创建者模式-单例模式

104 阅读3分钟

单例模式

单例模式 (Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式的结构

单例模式的主要有以下角色

  • 单例类。只能创建一个实例的类
  • 访问类。使用单例类

单例模式的实现

单例设计模式分为两种:

饿汉式:类加载就会导致该单例实例对象被创建

懒汉式:类加载不会导致该单例实例对象被创建,而是首次使用该对象是才会创建

1.饿汉式:(静态变量方式)

//饿汉式:静态成员变量
class Singleton {
//    1.私有化构造方法
   private init() {}
//    2.在本类中创建本类对象
    private static let instance = Singleton()
//    3.提供一个公共的访问方式,让外界获取该对象
    static func getInstance()->Singleton{
        return instance
    }
}
​

测试代码

//创建单例对象
var instance = Singleton.getInstance()
var instance1 = Singleton.getInstance()
print(1)
​

运行结果

image-20220910154731490

从打印结果可以看出,我们使用的是同于个对象

该方式在成员位置声明singleton类型的静态变量,并创建sinaleton类的对象instance。 instance对象是随着类的加载而创建的。如果该对象足够大的话,而一直没有使用就会造成内存的浪费。

懒汉式-方式1(线程不安全)

//懒汉式 线程不安全
class Singleton {
//    1.私有化构造方法
   private init() {}
//    2.声明Singleton类型的变量
    private static var instance:Singleton?
    static func getInstance()->Singleton{
        if instance == nil{ //此处线程不安全需要加锁
            instance = Singleton()
        }
        return instance!
    }
}

更改为线程安全的方式swift中@synchronized已经不存在了,可以利用其原理调用了objc_sync中的objc_sync_enterobjc_sync_exit方法来使用

懒汉式-方式2(线程安全)

class Singleton {
//    1.私有化构造方法
   private init() {}
//    2.声明Singleton类型的变量
    private static var instance:Singleton?
    static func  getInstance()->Singleton{
        objc_sync_enter(instance as Any)//加锁
        if instance == nil{//此处线程不安全需要加锁,一般没有必要只是有隐患
            sleep(1)
            instance = Singleton()
            print("创建对象")
        }
        objc_sync_exit(instance!)//解锁
        return instance!
    }
}

测试代码

for _ in 0...10{
        DispatchQueue.global().async {
            _ = Singleton.getInstance()
    }
}

测试结果

不加锁

image-20220910171430094

加锁

image-20220910171458323

懒汉式-方式3(双重检查锁)

再来讨论一下懒汉模式中加锁的问题,对于get Instance (〕方法来说,绝大部分的操作都是读操作,读操作是线程安全的,所以我们没必让每个线程必须持有锁才能调用该方法,我们需要调整加锁的时机。由此也产生了一种新的实现模式:双重检查锁模式

class Singleton {
//    1.私有化构造方法
   private init() {}
//    2.声明Singleton类型的变量
    private static var instance:Singleton?
    static func  getInstance()->Singleton{
//        第一次判断,如果instance的值不为nil,不需要抢占锁,直接返回对象
        if instance == nil{
//            此处进行第二次判断
            objc_sync_enter(instance as Any)
            if instance == nil{
                instance = Singleton()
                print("创建对象")
            }
            objc_sync_exit(instance!)
        }
        
        return instance!
​
    }
}

双重检查锁是一种非常好的单例实现模式,解决了单例、性能、线程安全的问题,但是不知道会不会出现类似java的空指针问题(未验证),整体是是完美无缺的一种方式。

懒汉式-方式4(内部类静态变量)

//懒汉式 内部类
class Singleton {
//    1.私有化构造方法
    private init() {}
//    2.定义一个内部类
    private class SingletonHolder{
//        在内部类中声明并初始化外部类对象
        static var instance = Singleton()
    }
//    提供公共的访问方式
    static func getInstance()->Singleton{
        return SingletonHolder.instance
    }
}

测试代码

var instance = Singleton.getInstance()
var instance1 = Singleton.getInstance()

运行结果

image-20220910174829114

以上是对应swift的单例模式,记录学习一下吧

感谢黑马程序员课程