Singleton(单例)模式是一种流行的创建对象的技术,确保在应用程序中只有一个实例。在 Swift 中,由于对静态属性和线程安全性的支持,singleton 模式的实现变得更加简单。
问题的历史:
在 Objective-C 中,实现 Singleton 需要较长且复杂的代码,以确保线程安全。在 Swift 中,这个问题通过懒加载静态属性得以解决。
问题:
Singleton 常用于集中访问应用程序状态(例如,Session、配置、服务),但不当使用会导致隐式依赖关系和降低代码测试性。
解决方案:
在 Swift 中,模式通过类型的静态常量实现。这保证了线程安全和唯一性:
代码示例:
final class Logger { static let shared = Logger() private init() {} func log(_ message: String) { print(message) } } Logger.shared.log("Singleton 工作示例")
关键特性:
是否(以及是否应该)始终为任何应用程序服务使用 singleton?
不应该。Singleton 适用于真正的全局状态(例如,ApplicationSettings),但将其用于业务逻辑服务是不正确的:会出现紧耦合和单元测试问题。
static let 是否提供了在 Swift 中线程安全的 Singleton 初始化?
是的,从 Swift 1.2 开始(以及由于 runtime 架构),static let 本质上是线程安全的——即使在线程竞争的情况下,也只会初始化一次。
singleton 是否可以被继承?
不可以。最好将类声明为 final,以避免继承——否则可能会创建不同子类的两个 singleton 实例,这破坏了模式本身的概念。
通过 singleton 实现的网络服务,其方法使用全局状态。在单元测试中会出现隐式依赖关系,无法复用服务。
优点:
缺点:
Singleton 仅用于真正的全局实体——例如,ApplicationConfig。所有服务通过显式注入器获取依赖关系。
优点:
缺点: