【问题标题】: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 声明做任何我想做的事情?

【问题讨论】:

标签: ios swift singleton cocoa-design-patterns


【解决方案1】:

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

  1. 类方法使单元测试更难
  2. 你需要依赖注入的类实例
  3. 如果稍后您决定非单例更合适 - 例如你决定为“myVariable”设置两个持久性存储,然后你就卡住了
  4. 最后,类成员生活在全局空间中,我们应该避免使用全局变量

您应该问的真正问题是,您是否真的需要一个单例(有或没有共享实例)来解决您的问题。如果拥有单例的唯一原因是易于访问,那么您真的不需要单例。

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
    

    顺便说一下,这种(你的)方法非常有用,在某些情况下可能是首选。

    【讨论】:

      猜你喜欢
      • 2014-05-05
      • 1970-01-01
      • 1970-01-01
      • 2017-12-18
      • 1970-01-01
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      • 2021-01-08
      相关资源
      最近更新 更多