Мне действительно нужен общий экземпляр на синглтоне?
Я написал вспомогательную структуру для сохранения и загрузки материала в 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 ответа
Общий экземпляр рекомендуется, по крайней мере, по следующим причинам:
- методы класса затрудняют юнит-тестирование
- вам нужны экземпляры классов для внедрения зависимостей
- если позже вы решите, что не-синглтон является более подходящим - например, вы решили иметь два постоянных хранилища для "myVariable", то вы застряли
- и не в последнюю очередь, ученики живут в глобальном пространстве, и мы должны избегать использования глобалов
Реальный вопрос, который вы должны задать, заключается в том, действительно ли вам нужен синглтон (с общим экземпляром или без него) для вашей проблемы. Если единственной причиной наличия синглтона является простота доступа, то вам не нужен синглтон.
PS На objc.io есть очень хорошая статья о синглетонах, и, хотя она была написана для Objective-C, многие из них применимы и в Swift.
// 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
Кстати, этот (ваш) подход может быть очень полезным и может быть предпочтительным в некоторых ситуациях.