Singleton-Muster
Teil des Abschnitts Objektorientierte Programmierung der Swift-Journey von Coddy. Lektion 42 von 57.
Ein Entwurfsmuster ist eine bewährte Lösung für ein häufiges Entwurfsproblem. Das Singleton-Muster stellt sicher, dass eine Klasse genau eine Instanz hat, die von überall aus erreichbar ist. In Swift ist es ein static let, das die Instanz enthält, zusammen mit einem private init, sodass niemand eine weitere erstellen kann:
final class Settings {
static let shared = Settings()
var theme = "light"
private init() {}
}
Settings.shared.theme = "dark"
print(Settings.shared.theme)Ausgabe:
darkJede Verwendung von Settings.shared verweist auf dasselbe Objekt, sodass eine Änderung in einem Teil des Programms überall sichtbar ist. static let wird bei der ersten Verwendung verzögert und sicher erstellt, selbst wenn mehrere Threads gleichzeitig starten:
final class Counter {
static let shared = Counter()
private(set) var hits = 0
private init() {}
func hit() { hits += 1 }
}
func pageA() { Counter.shared.hit() }
func pageB() { Counter.shared.hit(); Counter.shared.hit() }
pageA()
pageB()
print(Counter.shared.hits)
print(Counter.shared === Counter.shared)Ausgabe:
3
trueDa der Initialisierer privat ist, lässt sich Settings() außerhalb der Klasse nicht kompilieren, wodurch das Versprechen „nur eines“ eingehalten wird:
// let other = Settings() // error: 'Settings' initializer is inaccessible due to 'private' protection levelVerwende Singletons sparsam. Ein Singleton ist ein globaler Zustand: Jeder Code kann ihn ändern, und Tests können nicht ohne Weiteres mit einer sauberen Kopie beginnen. Sie eignen sich für Dinge, die es wirklich nur einmal pro Programm gibt, etwa einen Logger oder die Konfiguration der App; ein Objekt als Parameter zu übergeben, ist oft klarer.
// klarer zum Testen: der Logger wird übergeben
func process(order: Order, log: Logger) { log.write("processing \(order.id)") }Aufgabe
EinfachVervollständige den Singleton Logger. Er verfügt über eine static let shared-Instanz, einen privaten Initialisierer, ein private(set)-Array mit entries sowie log(_:level:), das [INFO] message oder [ERROR] message speichert (level ist info oder error). errorCount ist eine berechnete Eigenschaft. Der bereitgestellte Code ruft Logger.shared aus zwei verschiedenen Funktionen auf, daher müssen beide auf dieselbe Instanz zugreifen.
Der bereitgestellte Code liest Zeilen im Format info,message oder error,message, leitet Info-Zeilen über handleInfo und Fehlerzeilen über handleError weiter, gibt anschließend jeden Eintrag und errors: 1 aus.
Dein Code gehört in Logger.swift und Functions.swift. main.swift enthält den bereitgestellten Eingabe-/Ausgabecode und darf nicht bearbeitet werden.
Probier es selbst
// Gelieferter Ein-/Ausgabecode: belasse ihn wie er ist
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
let p = line.split(separator: ",", maxSplits: 1).map(String.init)
if p[0] == "error" { handleError(p[1]) } else { handleInfo(p[1]) }
}
for e in Logger.shared.entries { print(e) }
print("errors: \(Logger.shared.errorCount)")
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Klassen und Objekte
Arbeiten mit DateienKlassen definierenMethoden und selfInitialisiererKlassen sind ReferenzenRückblick – Bibliotheksausweis4Kapselung
ZugriffskontrolleVon außen schreibgeschütztZustand schützenFehlschlagende InitialisiererRückblick – Bankkonto7Polymorphismus und Generika
PolymorphismusTypumwandlungGenerische FunktionenGenerische TypenZusammenfassung – Shape-Rechner2Strukturen und Werttypen
StrukturenWertsemantikVerändernde MethodenStruktur oder KlasseZusammenfassung – Inventarelement5Vererbung
UnterklassenMethoden überschreibenInitialisierer und superfinal und HierarchienRückblick – Mitarbeiterhierarchie8Standardprotokolle
CustomStringConvertibleEquatableComparableHashableRückblick – Benutzerdefiniertes Sortieren11Projekt: Bibliotheksverwaltung
Bücher und MitgliederBücher ausleihenÜbe selbstständig: Swift-Playground