Menu
Coddy logo textTech

Singleton Kalıbı

Coddy'nin R Journey'sinin Nesne Tabanlı Programlama bölümünün bir parçası. Ders 42 / 57.

tasarım deseni, tekrar tekrar ortaya çıkan bir tasarım problemine yönelik, kendini kanıtlamış bir çözümdür. singleton deseni, bir şeyin tam olarak bir örneğinin olmasını ve bu örneğe her yerden erişilebilmesini sağlar. R'de bir erişimci işlevi, ilk çağrılışında örneği oluşturur, onu local() ile oluşturulmuş bir değişkende tutar ve her seferinde aynı örneği döndürür:

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))

Çıktı:

dark TRUE

Örnek bir ortamdır; bu nedenle bir çağrı aracılığıyla yapılan değişiklik programın diğer tüm bölümleri tarafından görülür. Farklı yerlerdeki iki işlev aynı günlüğe yazar:

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)

Çıktı:

[1] "a visited" "b visited" "a visited"

Örnek yalnızca ilk ihtiyaç duyulduğunda oluşturulur. Oluşturma sayısı, erişim işlevi kaç kez çağrılırsa çağrılsın bunun bir kez gerçekleştiğini gösterir:

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)")

Çıktı:

created 1 time(s)

Singleton’ları ölçülü kullanın. Bir singleton global durumdur: herhangi bir kod onu değiştirebilir ve bir test, sıfırlamadan temiz bir kopyayla başlayamaz. Günlükleyici veya ayarlar gibi program başına gerçekten bir tane olan şeyler için uygundur; bir nesneyi bağımsız değişken olarak geçirmek çoğu zaman daha anlaşılırdır:

# test için daha net: log içeriye geçiriliyor
process <- function(order, log) {
  log$lines <- c(log$lines, paste("processing", order$id))
}
challenge icon

Görev

Kolay

Logger.R içindeki singleton günlükleyiciyi tamamla. get_logger(), ilk çağrıda oluşturulan ve entries alanını (character türünde, başlangıçta boş) içeren tek bir ortam döndürür. Ardından şunları yaz:

  • Paylaşılan günlükleyicinin girişlerine [INFO] msg veya [ERROR] msg ekleyen log_info(msg) ve log_error(msg);
  • [ERROR] ile başlayan girişleri sayan error_count().

Sağlanan kod info,started veya error,disk full satırlarını okur, her birini günlüğe kaydeder, ardından her girişi, hata sayısını ve get_logger() işlevine yapılan iki çağrının aynı nesneyi döndürüp döndürmediğini yazdırır.

Kodun Logger.R dosyasına yazılmalıdır. main.R sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

source("Logger.R")

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
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 = "")
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Tabanlı Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online R derleyicisi