싱글턴 패턴
Coddy R 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 42번째.
디자인 패턴은 반복해서 발생하는 디자인 문제에 대한 검증된 해결책입니다. 싱글턴 패턴은 어떤 대상의 인스턴스가 정확히 하나만 존재하고 어디서든 접근할 수 있도록 합니다. R에서는 접근자 함수가 처음 호출될 때 인스턴스를 생성하고, local()로 만든 변수에 이를 보관한 다음, 호출할 때마다 동일한 인스턴스를 반환합니다:
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))출력:
dark TRUE인스턴스는 환경이므로 한 번의 호출을 통해 이루어진 변경 사항은 프로그램의 다른 모든 부분에서 확인할 수 있습니다. 서로 다른 위치에 있는 두 함수가 동일한 로그에 기록합니다.
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)출력:
[1] "a visited" "b visited" "a visited"인스턴스는 처음 필요할 때만 생성됩니다. 생성 횟수를 세어 보면 접근자가 몇 번 호출되든 한 번만 생성되는 것을 확인할 수 있습니다:
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)")출력:
created 1 time(s)싱글턴은 신중하게 사용하세요. 싱글턴은 전역 상태이므로 어떤 코드든 이를 변경할 수 있고, 재설정하지 않으면 테스트를 깨끗한 복사본에서 시작할 수 없습니다. 로거 또는 설정처럼 프로그램당 실제로 하나만 존재하는 것에 적합합니다. 객체를 인수로 전달하는 편이 더 명확한 경우가 많습니다.
# 테스트하기에 더 명확함: log가 전달됨
process <- function(order, log) {
log$lines <- c(log$lines, paste("processing", order$id))
}챌린지
쉬움Logger.R에서 싱글턴 로거를 완성하세요. get_logger()는 첫 번째 호출 시 생성되는 하나의 환경을 반환하며, 이 환경에는 entries 필드가 있습니다(문자형이며, 처음에는 비어 있음). 그런 다음 다음을 작성하세요:
log_info(msg)와log_error(msg)는 공유 로거의 entries에[INFO] msg또는[ERROR] msg를 추가합니다;error_count()는[ERROR]로 시작하는 entries의 개수를 셉니다.
제공된 코드는 info,started 또는 error,disk full 형식의 줄을 읽고, 각 줄을 기록한 다음 모든 entry, 오류 개수, 그리고 get_logger()를 두 번 호출했을 때 동일한 객체를 반환하는지를 출력합니다.
코드는 Logger.R에 작성하세요. main.R에는 제공된 입력/출력 코드가 있으며 편집할 수 없습니다.
직접 해보기
source("Logger.R")
# 제공된 입력/출력 코드: 그대로 유지하세요
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 = "")
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 R 컴파일러