Singleton-Muster
Teil des Abschnitts Objektorientierte Programmierung der R-Journey von Coddy. Lektion 42 von 57.
Ein Entwurfsmuster ist eine bewährte Lösung für ein Entwurfsproblem, das immer wieder auftritt. Das Singleton-Muster stellt sicher, dass es genau eine Instanz von etwas gibt, die von überall aus erreichbar ist. In R erstellt eine Zugriffsfunktion die Instanz bei ihrem ersten Aufruf, bewahrt sie in einer mit local() erstellten Variable auf und gibt jedes Mal dieselbe zurück:
get_config <- local({
instance <- NULL
function() {
if (is.null(instance)) {
instance <<- new.env()
instance$theme <- "light"
}
instance
}
})
a <- get_config()
a$theme <- "dark"
b <- get_config()
cat(b$theme, identical(a, b))Ausgabe:
dark TRUEDie Instanz ist eine Umgebung, daher wird eine Änderung, die durch einen Aufruf vorgenommen wurde, von jedem anderen Teil des Programms gesehen. Zwei Funktionen an unterschiedlichen Stellen schreiben in dasselbe Protokoll:
get_log <- local({
instance <- NULL
function() {
if (is.null(instance)) {
instance <<- new.env()
instance$lines <- character(0)
}
instance
}
})
page_a <- function() {
log <- get_log()
log$lines <- c(log$lines, "a visited")
}
page_b <- function() {
log <- get_log()
log$lines <- c(log$lines, "b visited")
}
page_a()
page_b()
page_a()
print(get_log()$lines)Ausgabe:
[1] "a visited" "b visited" "a visited"Die Instanz wird erst erstellt, wenn sie zum ersten Mal benötigt wird. Das Zählen der Erstellungen zeigt, dass dies einmal geschieht, unabhängig davon, wie oft der Zugriff aufgerufen wird:
created <- 0
get_db <- local({
instance <- NULL
function() {
if (is.null(instance)) {
created <<- created + 1
instance <<- new.env()
}
instance
}
})
for (i in 1:5) db <- get_db()
cat("created", created, "time(s)")Ausgabe:
created 1 time(s)Verwende Singletons sparsam. Ein Singleton ist ein globaler Zustand: Jeder Code kann ihn ändern, und ein Test kann nicht mit einer sauberen Kopie starten, ohne ihn zurückzusetzen. Er eignet sich für Dinge, die tatsächlich nur einmal pro Programm existieren, etwa einen Logger oder die Einstellungen; ein Objekt als Argument zu übergeben, ist oft klarer:
# klarer zum Testen: der log wird übergeben
process <- function(order, log) {
log$lines <- c(log$lines, paste("processing", order$id))
}Aufgabe
EinfachVervollständige den Singleton-Logger in Logger.R. get_logger() gibt eine Umgebung zurück, die beim ersten Aufruf erstellt wird und das Feld entries enthält (character, anfangs leer). Schreibe anschließend:
log_info(msg)undlog_error(msg), die[INFO] msgoder[ERROR] msgzu den Einträgen des gemeinsam genutzten Loggers hinzufügen;error_count(), das die Einträge zählt, die mit[ERROR]beginnen.
Der bereitgestellte Code liest Zeilen wie info,started oder error,disk full, protokolliert jede Zeile und gibt anschließend jeden Eintrag, die Anzahl der Fehler sowie aus, ob zwei Aufrufe von get_logger() dasselbe Objekt zurückgeben.
Dein Code gehört in Logger.R. main.R enthält den bereitgestellten Eingabe-/Ausgabecode und darf nicht bearbeitet werden.
Probier es selbst
source("Logger.R")
# Bereitgestellter Ein-/Ausgabe-Code: belasse ihn wie er ist
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, ",")[[1]]
if (p[1] == "error") log_error(p[2]) else log_info(p[2])
}
for (e in get_logger()$entries) cat(e, "\n", sep = "")
cat("errors: ", error_count(), "\n", sep = "")
cat("one logger: ", identical(get_logger(), get_logger()), "\n", sep = "")
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1S3-Grundlagen
Arbeiten mit DateienListen mit einer KlasseKonstruktorfunktionenPrint- und Format-MethodenValidatoren und HilfsfunktionenRückblick – Temperaturen4Kapselung in R
Closures als ObjekteUmgebungen als ObjekteZugriffsfunktionenZustand schützenRückblick – Parkuhr2S3-Generics und Methoden
Generics und UseMethodStandardmethodenMethoden für Basis-GenericsGrundlagen von NextMethodWiederholung – Flächeninhalte von Formen5S4-Klassen
S4-Klassen definierenSlots und ZugriffGültigkeitsprüfungenShow-MethodenRückblick – Produktkatalog8Referenzklassen
Referenzklassen definierenMethoden und FeldänderungenKopiersemantikVererbung und callSuperZusammenfassung – Aufgabenwarteschlange11Projekt: Bibliotheksverwaltung
Bücher und MitgliederBücher ausleihenÜbe selbstständig: Online-R-Compiler