Menu
Coddy logo textTech

Fabrika Kalıbı

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

Bir factory, çağıranın sınıfı veya onun oluşturucusunu bilmesine gerek kalmaması için nesneler oluşturan bir işlevdir. Tür adı gibi bir açıklama alır ve doğru nesneyi döndürür:

area <- function(s) UseMethod("area")
area.circle <- function(s) pi * s$r^2
area.square <- function(s) s$side^2
make_shape <- function(type, size) {
  switch(type,
    circle = structure(list(r = size), class = "circle"),
    square = structure(list(side = size), class = "square"))
}
for (t in c("circle", "square")) cat(t, round(area(make_shape(t, 2)), 2), "\n")

Çıktı:

circle 12.57 
square 4 

Bilmediği bir tür için switch(), NULL döndürür. Bir fabrika bunun yerine türü adlandıran bir mesajla durmalıdır; böylece hata, yapıldığı yerde görünür:

make_shape <- function(type, size) {
  switch(type,
    circle = structure(list(r = size), class = "circle"),
    square = structure(list(side = size), class = "square"),
    stop("unknown shape: ", type, call. = FALSE))
}
msg <- tryCatch(make_shape("hexagon", 1), error = function(e) conditionMessage(e))
cat(msg)

Çıktı:

unknown shape: hexagon

Kayıt defteri, oluşturucuları adlandırılmış bir listede tutar; böylece fabrikanın kendisi hiçbir zaman değişmez. Burada kayıt defteri bir ortamdır ve register_shape(), program çalışırken yeni bir tür ekler:

registry <- new.env()
register_shape <- function(name, maker) assign(name, maker, envir = registry)
make_shape <- function(name, ...) {
  if (!exists(name, envir = registry, inherits = FALSE)) stop("unknown shape: ", name, call. = FALSE)
  get(name, envir = registry)(...)
}
register_shape("circle", function(r) structure(list(r = r), class = "circle"))
register_shape("rect", function(w, h) structure(list(w = w, h = h), class = "rect"))
print(class(make_shape("rect", 2, 3)))
print(sort(ls(registry)))

Çıktı:

[1] "rect"
[1] "circle" "rect"  

Nesneleri kullanan kod yalnızca area() gibi jeneriklere bağlıdır. Kaydedilen ve bir area() yöntemine sahip yeni bir sınıf, bu kodla hiçbir değişiklik yapılmadan çalışır:

registry <- new.env()
register_shape <- function(name, maker) assign(name, maker, envir = registry)
make_shape <- function(name, ...) get(name, envir = registry)(...)
area <- function(s) UseMethod("area")
total_area <- function(shapes) sum(vapply(shapes, area, numeric(1)))
register_shape("square", function(a) structure(list(a = a), class = "square"))
area.square <- function(s) s$a^2
register_shape("tri", function(b, h) structure(list(b = b, h = h), class = "tri"))
area.tri <- function(s) s$b * s$h / 2
print(total_area(list(make_shape("square", 2), make_shape("tri", 4, 3))))

Çıktı:

[1] 10
challenge icon

Görev

Kolay

Bir kayıt çeşitli biçimlerde dışa aktarılabilir. Exporters.R, genel export(exporter, record) işlevini ve değerleri virgüllerle birleştirerek döndüren csv_exporter yöntemini içerir. Buradaki diğer iki yöntemi tamamlayın:

  • json_exporter: {"name": "Ada", "age": "36"};
  • text_exporter: name=Ada; age=36.

Ardından Factory.R içinde make_exporter(format) fabrikasını yazın: csv, json veya text, sınıfı sırasıyla csv_exporter, json_exporter veya text_exporter olan boş bir liste döndürür; diğer tüm biçimler unknown format: xml ile durur (call. = FALSE kullanın). Sağlanan kod alan adlarını ve değerleri, ardından biçim adlarını okur ve her dışa aktarımı ya da error: ile mesajı yazdırır.

Kodunuz Exporters.R ve Factory.R dosyalarına yazılmalıdır. main.R sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

source("Exporters.R")
source("Factory.R")

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
input <- suppressWarnings(readLines(file("stdin")))
fields <- strsplit(input[1], ",")[[1]]
values <- strsplit(input[2], ",")[[1]]
record <- setNames(values, fields)
for (fmt in input[-(1:2)]) {
  out <- tryCatch(export(make_exporter(fmt), record), error = function(e) paste("error:", conditionMessage(e)))
  cat(out, "\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