不使用'Static'也能创建单例class?
Singleton class can be created without using 'Static'?
我们使用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() }
}
"write-only" 事物存在的情况并不少见,其中您有一个 API 用于设置值(例如微型数字输出引脚的 on/off 状态控制器),但没有相应的 API 用于检查状态。在这种情况下,您的程序需要通过将状态保存到变量来记住状态,并确保 "remembered state" 和真实硬件始终一起更新。
此实现确保正确完成,因为 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)
}
}
但是您确实需要某种形式的静态存储(全局变量、静态存储、class 存储)。除非有一个实例,否则实例存储(存储属性)实际上并不分配内存。而且由于没有实例来存储单例引用,所以它没有任何意义。
我们使用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() }
}
"write-only" 事物存在的情况并不少见,其中您有一个 API 用于设置值(例如微型数字输出引脚的 on/off 状态控制器),但没有相应的 API 用于检查状态。在这种情况下,您的程序需要通过将状态保存到变量来记住状态,并确保 "remembered state" 和真实硬件始终一起更新。
此实现确保正确完成,因为 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)
}
}
但是您确实需要某种形式的静态存储(全局变量、静态存储、class 存储)。除非有一个实例,否则实例存储(存储属性)实际上并不分配内存。而且由于没有实例来存储单例引用,所以它没有任何意义。