我真的需要单身人士的共享实例吗?

时间:2016-01-04 15:08:16

标签: ios swift singleton cocoa-design-patterns

我编写了一个帮助程序结构,用于保存和加载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()myVariable加载NSUSerDefaults即可。 但是,使用此代码可以实现相同的目的:

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的用途是什么?

2 个答案:

答案 0 :(得分:1)

建议使用共享实例,至少出于以下原因:

  1. 类方法使单元测试更难
  2. 您需要依赖注入的类实例
  3. 如果您以后决定非单身人士更合适 - 例如你决定为" myVariable"设置两个持久性存储空间,然后你就会被卡住
  4. 而不是最后,班级成员居住在全球空间,我们应该避免使用全局
  5. 你应该问的真正问题是,你是否真的需要一个单例(有或没有共享实例)来解决你的问题。如果拥有单身人士的唯一理由是易于访问,那么你真的不需要单身人士。

    P.S。关于单身人士有很好的article on objc.io,虽然它是为Objective-C编写的,但其中的许多概念也适用于Swift。

答案 1 :(得分:0)

// 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
顺便说一句,这个(你的)方法非常有用,在某些情况下可能更受欢迎。