Мне действительно нужен общий экземпляр на синглтоне?

Я написал вспомогательную структуру для сохранения и загрузки данных в 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?


person MJQZ1347    schedule 04.01.2016    source источник


Ответы (2)


Общий экземпляр рекомендуется, по крайней мере, по следующим причинам:

  1. методы класса усложняют модульное тестирование
  2. вам нужны экземпляры класса для внедрения зависимостей
  3. если позже вы решите, что больше подходит не синглтон - например. вы решили иметь два постоянных хранилища для «myVariable», тогда вы застряли
  4. и не в последнюю очередь, члены класса живут в глобальном пространстве, и нам следует избегать использования глобалов

Реальный вопрос, который вы должны задать, заключается в том, действительно ли вам нужен синглтон (с общим экземпляром или без него) для вашей проблемы. Если единственной причиной для использования синглтона является простота доступа, то вам на самом деле не нужен синглтон.

P.S. На objc.io есть очень хорошая статья. a> о синглтонах, и хотя он был написан для Objective-C, многие концепции оттуда применимы и в Swift.

person Cristik    schedule 04.01.2016

// 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

кстати, этот (ваш) подход может быть очень полезен и может быть предпочтительным в некоторых ситуациях.

person user3441734    schedule 04.01.2016