从Objective-C到Swift 单例模式

在Objective-C中经常会用到单例模式。最常见的就是:

[UIApplication sharedApplication].delegate

这里的sharedApplication就是一个返回单例的方法。所谓的单例模式也就是在整个APP、或者软件中只有这个类的这么一个对象。可以保存一些全局的设置等数据,达到单例对象变了整个app的全部设置都更新的效果。

忽略OC的代码,直接进入Swift代码。

第一种单例模式的实现:

class Singleton1{
    class var sharedInstance: Singleton1 {
        return _SharedInstance
    }
}
private let _SharedInstance = Singleton1()

var s1 = Singleton1()

这是第一种,最简单的单例模式的实现。在需要单例实现的类外面声明一个全局的私有常量,private let _SharedInstance = Singleton1()。之后,在单例类的computed property中声明一个类属性,并在其中返回这个类外面的单例类的实例。非常简单,但是有效的方法!

第二种单例的实现:

class Singleton2{
    class var sharedInstance: Singleton2{
        struct Instance{
            static let instance: Singleton2 = Singleton2()
        }
        return Instance.instance
    }
}

var s2 = Singleton2()

这个实现用到的是内嵌类型。在computd property中定义了一个结构体。并在整个结构体中声明了一个静态的(class里面用的就是class关键字来声明静态的方法或者属性的)常量属性初始化了一个单例的实例。并在单例类的computed property中返回结构体总的实例。

第三种单例:

class Singleton3{
    class var sharedInstance: Singleton3{
        struct Instance {
            static var onceToken: dispatch_once_t = 0
            static var instance: Singleton3? = nil
        }
        dispatch_once(&Instance.onceToken){
            Instance.instance = Singleton3()
        }
        return Instance.instance!
    }
}

var s3 = Singleton3()

这个实现用到的是类似于OC中GCD的东西。这个单例是线程安全的。其实现方式类似于第二种单例,只是加了线程锁,保证了多线程情况下可以安全的调用。

实现单例模式的关键就是在于单例的类的构造函数不能被随意的访问。咱们的这些实现方式其实都可以任意的初始化实例。其能达到的效果是在按照约定的调用方式可以达到单例的效果。在以上的实现中。第一种定义了一个私有的常量实例,在约定的调用方法之外,其他的类是访问不到这个私有常量的。第二种和第三种比较类似,都是在computed property中定义了一个嵌套类型。这样,在其他的类对象中无法访问到这个computed property中的内嵌类型。第二、三种点不同之处就在于,第二种是直接在结构体里就初始化了单例的实例,而第三种是在computed property里实现了线程安全的机制。