swift - 可以在不使用“静态”的情况下创建单例类吗?
问题描述
我们使用Static
声明singleton
,因此只会创建一个实例。是否可以在不使用的情况下声明单例Static
?如果是,可以覆盖实例吗?
class SingletonClass {
static let shared = SingletonClass();
func requestToAccess() {
// Print statement
}
}
解决方案
这里有很多问题,所以让我们先解决这些问题:
- 这是无效的 Swift 代码。
Class
并且Static
两者都必须小写。 - Swift 中的类型名称应该是 UpperCamelCase。
- 格式很奇怪。
解决这个问题,我们得到:
class SingletonClass {
static let shared = SingletonClass()
func requestToAccess() {
print(SingletonClass.shared)
}
}
您在这里拥有的是一个共享实例,但实际上并不是一个单例。单身人士的关键定义特征是它很好……单身。这里根本不是这样,因为绝对没有什么能阻止我说:
let myOwnInstance = SingletonClass()
单例通常用于对单一物理资源的状态进行建模。如果存在两个实例,它们可能会相互干扰。考虑这个例子,一个(有缺陷的)单例试图在一个硬件上模拟单个 LED:
public class UserActivityIndicatorLED {
public static let shared = UserActivityIndicatorLED()
public private(set) var currentState: Bool = false {
didSet {
if currentState { turnLEDOn() }
else { turnLEDOff() }
}
}
public func toggle() { self.currentState.toggle() }
}
存在“只写”事物的情况并不少见,其中您有一个用于设置值的 API(例如微控制器的数字输出引脚的开/关状态),但没有用于检查状态的相应 API . 在这种情况下,您的程序需要通过将状态保存到变量来记住状态,并确保“记住的状态”和真实硬件始终一起更新。
此实现确保正确完成,因为turnLEDOn
并且turnLEDOff
只能通过改变 currentState 来调用。但是,由于违反了单例属性,因此可能会发生这种情况:
UserActivityIndicatorLED.shared().toggle() // => UserActivityIndicatorLED.shared().currentState becomes true, LED turns on
let myInstance = UserActivityIndicatorLED() // => I create a new instance, violating the singleton pattern
myInstance.toggle() // myInstance.currentState becomes true, LED is made to turn on again (it just stays on)
myInstance.toggle() // myInstance.currentState becomes false, LED is turned off, but UserActivityIndicatorLED.shared().currentState is still true!
// Now the system's "memory" of the physical state is desynchronized from the
// "true hardware" state, because creating a new instance of `UserActivityIndicatorLED`
// permitting the mutation of the hardware state without a corresponding update to the
// memorized state.
// Some user calls this again, expecting the LED to turn off, but surprise, it's already off!
UserActivityIndicatorLED.shared().toggle() // UserActivityIndicatorLED.shared().currentState becomes false, but the light was already off
为了解决这个问题,并确保你实际上有一个单例,初始化器需要设为私有,这样新实例只能在 内创建SingletonClass
,并且对初始化器的唯一调用是shared
变量:
class SingletonClass {
static let shared = SingletonClass()
private init() { }
func requestToAccess() {
print(SingletonClass.shared)
}
}
我需要使用静态变量吗?
不一定,您可以使用全局变量,但更糟糕的是:
let SingletonClassShared = SingletonClass()
class SingletonClass {
fileprivate init() { }
func requestToAccess() {
print(SingletonClass.shared)
}
}
但是您是否需要某种形式的静态存储(全局变量、静态存储、类存储)。除非有实例,否则实例存储(存储属性)实际上不会分配内存。而且由于没有实例可以存储单例引用,因此它没有任何意义。
推荐阅读
- php - Laravel Horizon 在 /horizon 上给出 404
- encoding - JMeter 变量编码不正确
- firebase - Firebase crashlytics:非注册测试人员注册
- javascript - 有没有办法通过 forEach() 返回与 JavaScript 函数中指定的条件匹配的文档?
- laravel - 使用 Sendgrid 将电子邮件回复与原始电子邮件(电子邮件线程)相关联
- c# - 如何在菜单项单击时切换视图?
- c# - C# - 向 Telnet 服务器发送命令(纯文本)
- vue.js - Vue图表js动态雷达图
- mysql - 如何使用邻接列表模型从 MySQL 分层类别树中获取数据?
- c# - C# Monogame,试图创建一个 2D 赛车 AI