我真的需要单例上的共享实例吗?
Posted
技术标签:
【中文标题】我真的需要单例上的共享实例吗?【英文标题】:Do I really need a shared instance on a singleton? 【发布时间】:2016-01-04 15:08:16 【问题描述】:我已经写了一个辅助结构来保存和加载东西到NSUserDefaults
。
import UIKit
struct Database
static let defaults = NSUserDefaults.standardUserDefaults()
static var myVariable: AnyObject?
static func save()
defaults.setObject(myVariable, forKey: "myVariable")
static func load()
if let myVariable = defaults.objectForKey("myVariable")
self.myVariable = myVariable
static func clear()
defaults.removeObjectForKey("myVariable")
现在我可以简单地使用Database.load()
从NSUSerDefaults
加载myVariable
。
但是,使用此代码也可以实现相同的目标:
struct Database2
static var sharedInstance = Database()
let defaults = NSUserDefaults.standardUserDefaults()
var myVariable: AnyObject?
func save()
defaults.setObject(myVariable, forKey: "myVariable")
func load()
if let myVariable = defaults.objectForKey("myVariable")
self.myVariable = myVariable
func clear()
defaults.removeObjectForKey("myVariable")
现在我会使用Database2.sharedInstance.load()
。
哪一个被认为是更好的做法,为什么? sharedInstance
有什么用,如果我可以使用 static
声明做任何我想做的事情?
【问题讨论】:
With the Objective-C/Swift Singleton model, why do we create a shared instance and not just use class methods?的可能重复 【参考方案1】:推荐使用共享实例,至少出于以下原因:
-
类方法使单元测试更难
你需要依赖注入的类实例
如果稍后您决定非单例更合适 - 例如你决定为“myVariable”设置两个持久性存储,然后你就卡住了
最后,类成员生活在全局空间中,我们应该避免使用全局变量
您应该问的真正问题是,您是否真的需要一个单例(有或没有共享实例)来解决您的问题。如果拥有单例的唯一原因是易于访问,那么您真的不需要单例。
P.S.有一个关于单例的非常好的article on objc.io,虽然它是为 Objective-C 编写的,但其中的许多概念也适用于 Swift。
【讨论】:
【参考方案2】:// with singleton pattern, there exist only one copy of the object
// sigleton pattern can be applied for reference type only
// let st1 = Singleton(); let st2 = Sigleton(); st1 === st2
// in your example, S is value type. All instances of S share only type properties, here only i
struct S
static var i: Int = 100
var j: Int
func foo()
//print(i) // error: static member 'i' cannot be used on instance of type 'S'
print(S.i)
init(_ j: Int)
self.j = j
var s1 = S(1)
var s2 = S(2)
//s1.i // error: static member 'i' cannot be used on instance of type 'S'
S.i // 100
s1.foo() // 100
s1.j // 1
s2.foo() // 100
s2.j // 2
S.i = 200
s1.foo() // 200
s2.foo() // 200
顺便说一下,这种(你的)方法非常有用,在某些情况下可能是首选。
【讨论】:
以上是关于我真的需要单例上的共享实例吗?的主要内容,如果未能解决你的问题,请参考以下文章