Menu
CoddyTech

Pola Singleton

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan R di Coddy. Pelajaran 42 dari 57.

design pattern adalah solusi teruji untuk masalah desain yang berulang kali muncul. Pola singleton memastikan hanya ada satu instance dari sesuatu yang dapat diakses dari mana saja. Di R, fungsi pengakses membuat instance saat pertama kali dipanggil, menyimpannya dalam variabel yang dibuat dengan local(), lalu mengembalikan instance yang sama setiap kali:

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

Output:

dark TRUE

Instance adalah sebuah environment, jadi perubahan yang dibuat melalui satu pemanggilan akan terlihat oleh setiap bagian lain dari program. Dua fungsi di tempat berbeda menulis ke log yang sama:

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)

Output:

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

Instance dibuat hanya saat pertama kali dibutuhkan. Dengan menghitung jumlah pembuatannya, terlihat bahwa instance dibuat satu kali, seberapa sering pun accessor dipanggil:

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

Output:

created 1 time(s)

Gunakan singleton seperlunya. Singleton adalah state global: kode apa pun dapat mengubahnya, dan test tidak dapat dimulai dari salinan bersih tanpa meresetnya. Singleton cocok untuk hal-hal yang benar-benar hanya ada satu per program, seperti logger atau pengaturan; sering kali, meneruskan object sebagai argumen lebih jelas:

# Lebih mudah diuji: log diberikan sebagai argumen
process <- function(order, log) {
  log$lines <- c(log$lines, paste("processing", order$id))
}
challenge icon

Tantangan

Mudah

Lengkapi logger singleton di Logger.R. get_logger() mengembalikan satu environment yang dibuat pada pemanggilan pertama, dengan field entries (character, awalnya kosong). Lalu tulis:

  • log_info(msg) dan log_error(msg), yang menambahkan [INFO] msg atau [ERROR] msg ke entries pada logger bersama;
  • error_count(), yang menghitung entries yang diawali dengan [ERROR].

Kode yang disediakan membaca baris info,started atau error,disk full, mencatat masing-masing, lalu mencetak setiap entry, jumlah error, dan apakah dua pemanggilan get_logger() mengembalikan object yang sama.

Tulis kodemu di Logger.R. main.R berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

source("Logger.R")

# Kode input/output yang disediakan: biarkan apa adanya
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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler R online