我们使用Static
来声明singleton
,因此将仅创建一个实例。是否可以在不使用Static
的情况下声明单例?如果是,实例是否可以被覆盖?
class SingletonClass {
static let shared = SingletonClass();
func requestToAccess() {
// Print statement
}
}
答案 0 :(得分:2)
这里有很多问题,所以让我们先清除一下这些问题:
Class
和Static
都必须小写。解决此问题,我们得到:
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进行更改来调用。但是,由于违反了singleton属性,因此可能会发生:
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)
}
}
但是您需要某种形式的静态存储(全局变量,静态存储,类存储)。除非有实例,否则实例存储(存储的属性)实际上不会分配内存。而且,由于没有实例可以存储单例引用,因此这没有任何意义。