Padrão Singleton
Parte da seção Programação Orientada a Objetos do Journey de R da Coddy. Lição 42 de 57.
Um padrão de projeto é uma solução comprovada para um problema de projeto que surge repetidamente. O padrão singleton garante que exista exatamente uma instância de algo, acessível de qualquer lugar. Em R, uma função acessora cria a instância em sua primeira chamada, mantém-na em uma variável criada com local() e retorna a mesma todas as vezes:
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))Saída:
dark TRUEA instância é um ambiente, portanto uma alteração feita por meio de uma chamada é vista por todas as outras partes do programa. Duas funções em lugares diferentes escrevem no mesmo log:
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)Saída:
[1] "a visited" "b visited" "a visited"A instância é criada somente quando é necessária pela primeira vez. Contar as criações mostra que isso acontece uma vez, independentemente de quantas vezes o acessador é chamado:
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)")Saída:
created 1 time(s)Use singletons com moderação. Um singleton é um estado global: qualquer código pode alterá-lo, e um teste não pode começar com uma cópia limpa sem redefini-lo. Ele é adequado para coisas que realmente existem uma vez por programa, como um logger ou as configurações; passar um objeto como argumento costuma ser mais claro:
# mais claro para testar: o log é passado
process <- function(order, log) {
log$lines <- c(log$lines, paste("processing", order$id))
}Desafio
FácilComplete o logger singleton em Logger.R. get_logger() retorna um ambiente, criado na primeira chamada, com o campo entries (de caracteres, inicialmente vazio). Em seguida, escreva:
log_info(msg)elog_error(msg), que adicionam[INFO] msgou[ERROR] msgàs entradas do logger compartilhado;error_count(), que conta as entradas que começam com[ERROR].
O código fornecido lê linhas info,started ou error,disk full, registra cada uma, depois imprime todas as entradas, o número de erros e se duas chamadas de get_logger() retornam o mesmo objeto.
Seu código deve ser colocado em Logger.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
source("Logger.R")
# Código de entrada/saída fornecido: mantenha-o 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 lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos do S3
Trabalhando com ArquivosListas com uma ClasseFunções ConstrutorasMétodos de Impressão e FormataçãoValidadores e AuxiliaresRevisão - Temperaturas4Encapsulamento em R
Closures como ObjetosAmbientes como ObjetosFunções de AcessoProtegendo o EstadoRecapitulação - Parquímetro2Genéricos e Métodos S3
Genéricos e UseMethodMétodos padrãoMétodos para genéricos baseFundamentos de NextMethodRevisão - Áreas de formas5Classes S4
Definindo classes S4Slots e acessoVerificações de validadeMétodos showRevisão - Catálogo de produtos8Classes de Referência
Definindo Classes de ReferênciaMétodos e Atualizações de CamposSemântica de CópiaHerança e callSuperRecapitulação — Fila de Tarefas11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Compilador de R online