iOS8 + Swift: 创建一个真正的单例类

4

我正在使用Swift创建一个单例类,代码如下:

class SingletonClass {

    class var sharedInstance: SingletonClass {
        struct Singleton {
            static let instance = SingletonClass()
        }

        return Singleton.instance
    }


    var a: Int?
    var b: Int?
    var c: Int?
}

这使得我可以从任何地方访问共享实例:
SingletonClass.sharedInstance

虽然这样可以工作,但它并没有使这个实例成为整个系统中唯一可能的实例,而这正是单例模式的目的。
这意味着我仍然可以创建一个全新的实例,如下所示:

let DifferentInstance: SingletonClass = SingletonClass()

现在共享实例不再是唯一的实例了。

那么我的问题是:在Swift中是否有一种方式可以创建真正的单例类,系统范围内只允许存在一个实例?


为什么要强制禁止任何人创建一个类的实例? - Daniel Galasko
1
@DanielGalasko,比如说,如果你的类正在管理与某个物理资源的交互,那么多个实例与同一资源的交互可能会导致重大或致命的问题。或者,它只是在与一个无法同时打开多次的数据库进行交互。 - drewag
我明白你的意思,但不幸的是,没有办法防止别人的无知或愚蠢对你的框架造成影响。你最好的选择是在单例实例化中定义大部分对象设置方法,比如数据库URL等。 - Daniel Galasko
3个回答

14

只需将您的初始化程序声明为私有:

private init() {}

现在只能从同一文件内创建新实例。


2
你误解了单例的本质。单例的目的是提供一个单例,而不是防止恶意行为。我可以创建另一个UIApplication来代替sharedApplication,但这样做是愚蠢的,因为它不会是sharedApplication。我可以创建另一个NSNotificationCenter来代替defaultCenter,但这样做也是愚蠢的,因为它不会是defaultCenter。重点不是阻止我犯傻,而是提供一个工厂单例,而这正是你已经在做的事情。别担心,开心点。

1
是的,嗯,我有点犹豫于“愚蠢”和“邪恶”之间,这就是为什么我两个都用了。:) 面向对象编程是一种“契约”。任何人都可以违反契约(例如,如果你真的想要,你总是可以规避隐私限制)。然而,创意在于不要这样做。 - matt
3
然而,在可用性中的主要概念之一是“可供性”的概念。减少可能性会使某物更易于使用。尤其是当解决方案像将初始化程序设为私有(见我的回答)那样容易时,我认为最好这样做。此外,维基百科关于单例模式的第一行是“在软件工程中,单例模式是一种设计模式,将类的实例化限制为一个对象。”共享实例和单例之间存在区别。 - drewag
此外,拥有多个通知中心的想法并不疯狂,但是例如在计算机上只有一个相机时拥有多个相机对象的想法不仅不合逻辑,而且可能会在低级别上引起严重问题。有时候,真正的单例(强制单个实例)实际上是必要的,以防止严重的崩溃或错误。 - drewag
1
@matt 我必须在这里同意drewag的看法。你提供了使用共享实例的完美示例,不使用它们是相当愚蠢的:)。但这些仅是非常有用的共享实例,而不是单例。根据定义,单例类在任何给定时间只能有一个现有实例。在我的当前特定情况下,实际上并不重要我是否使用真正的单例,但让我感兴趣的是如何做到这一点。不知怎么地,我错过了显而易见的私有init解决方案。我猜这是工作量的缘故 :) - Darkshore Grouper
“防御性编程”争论...我支持这个答案。 - Nicolas Miari
显示剩余2条评论

0

全局变量,嵌套结构体,dispatch_once。请选择一个。

全局变量的懒加载初始化器(也适用于结构体和枚举类型的静态成员)在第一次访问该全局变量时运行,并作为dispatch_once启动,以确保初始化是原子性的。这使得在代码中使用dispatch_once的方式非常酷:只需声明一个带有初始化器的全局变量并将其标记为私有即可。

private let _singletonInstance = SingletonClass()
class SingletonClass {
  class var sharedInstance: SingletonClass {
    return _singletonInstance
  }
}

更多信息请点击此处。 https://github.com/hpique/SwiftSingleton


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接