Patrón Singleton
Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 42 de 57.
Un patrón de diseño es una solución comprobada para un problema de diseño que surge una y otra vez. El patrón singleton garantiza que exista exactamente una instancia de algo, accesible desde cualquier lugar. En R, una función de acceso crea la instancia en su primera llamada, la conserva en una variable creada con local() y devuelve la misma cada vez:
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))Salida:
dark TRUELa instancia es un entorno, por lo que un cambio realizado mediante una llamada es visible para cualquier otra parte del programa. Dos funciones en lugares diferentes escriben en el mismo registro:
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)Salida:
[1] "a visited" "b visited" "a visited"La instancia se crea únicamente cuando se necesita por primera vez. Contar las creaciones muestra que ocurre una vez, sin importar con qué frecuencia se llame al accessor:
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)")Salida:
created 1 time(s)Usa los singletons con moderación. Un singleton es un estado global: cualquier código puede cambiarlo, y una prueba no puede comenzar con una copia limpia sin restablecerlo. Es adecuado para cosas que realmente son únicas por programa, como un logger o la configuración; pasar un objeto como argumento suele ser más claro:
# más claro para probar: el log se pasa
process <- function(order, log) {
log$lines <- c(log$lines, paste("processing", order$id))
}Desafío
FácilCompleta el registrador singleton en Logger.R. get_logger() devuelve un entorno, creado en la primera llamada, con el campo entries (de tipo character, vacío al principio). Después escribe:
log_info(msg)ylog_error(msg), que añaden[INFO] msgo[ERROR] msga las entradas del registrador compartido;error_count(), que cuenta las entradas que comienzan con[ERROR].
El código proporcionado lee líneas info,started o error,disk full, registra cada una y después imprime todas las entradas, el número de errores y si dos llamadas a get_logger() devuelven el mismo objeto.
Tu código debe estar en Logger.R. main.R contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
source("Logger.R")
# Código de entrada/salida suministrado: déjalo tal como está
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 = "")
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Fundamentos de S3
Trabajar con archivosListas con una claseFunciones constructorasMétodos de impresión y formatoValidadores y auxiliaresRepaso: temperaturas4Encapsulación en R
Cierres como objetosEntornos como objetosFunciones de accesoProtección del estadoRepaso: parquímetro2S3 Genéricos y métodos
Genéricos y UseMethodMétodos predeterminadosMétodos para genéricos baseFundamentos de NextMethodRepaso: áreas de figuras5Clases S4
Definición de clases S4Slots y accesoComprobaciones de validezMétodos showRepaso - Catálogo de productos8Clases de referencia
Definición de clases de referenciaMétodos y actualizaciones de camposSemántica de copiaHerencia y callSuperRepaso: cola de tareas11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de R online