Patrón Decorator
Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 46 de 57.
Un decorador envuelve algo y añade comportamiento mientras mantiene la misma interfaz. Para una función, el decorador toma una función y devuelve una función nueva que realiza trabajo adicional alrededor de la llamada:
with_logging <- function(f, name) {
function(x) {
cat("calling", name, "with", x, "\n")
f(x)
}
}
double <- function(x) x * 2
logged <- with_logging(double, "double")
print(logged(21))Salida:
calling double with 21
[1] 42Un decorador puede recordar resultados. with_cache() conserva cada respuesta en un entorno y llama a la función envuelta solo para los argumentos nuevos:
with_cache <- function(f) {
cache <- new.env()
function(x) {
key <- as.character(x)
if (!exists(key, envir = cache, inherits = FALSE)) assign(key, f(x), envir = cache)
get(key, envir = cache)
}
}
work <- 0
slow_square <- function(x) {
work <<- work + 1
x^2
}
fast <- with_cache(slow_square)
for (x in c(3, 4, 3, 3, 4)) fast(x)
cat("results computed:", work)Salida:
results computed: 2Los objetos también pueden decorarse. Cada decorador es un objeto que mantiene el objeto que envuelve en un campo y responde a los mismos genéricos, añadiendo su parte y pidiendo al objeto interno el resto:
cost <- function(d) UseMethod("cost")
describe <- function(d) UseMethod("describe")
cost.coffee <- function(d) 2
describe.coffee <- function(d) "coffee"
with_milk <- function(inner) structure(list(inner = inner), class = "milk")
cost.milk <- function(d) cost(d$inner) + 0.5
describe.milk <- function(d) paste(describe(d$inner), "+ milk")
cup <- with_milk(with_milk(structure(list(), class = "coffee")))
cat(describe(cup), "=", cost(cup))Salida:
coffee + milk + milk = 3Los decoradores se apilan y su orden importa: el más externo se ejecuta primero al entrar y último al salir:
exclaim <- function(f) function(s) paste0(f(s), "!")
twice <- function(f) function(s) paste(f(s), f(s))
greet <- function(name) paste("hi", name)
a <- twice(exclaim(greet))
b <- exclaim(twice(greet))
cat(a("ada"), "/", b("ada"))Salida:
hi ada! hi ada! / hi ada hi ada!Desafío
FácilLas bebidas se decoran con extras. Drink.R contiene los métodos genéricos cost() y describe(), y la bebida base, new_coffee(), que cuesta 2 y se describe como coffee. En Extras.R, escribe tres decoradores, cada uno de los cuales es un objeto que contiene la bebida que envuelve en el campo inner:
add_milk(d): clasemilk, añade 0.50 y+ milk;add_sugar(d): clasesugar, añade 0.20 y+ sugar;add_syrup(d, flavour): clasesyrupcon el campoflavour, añade 0.80 y+ vanilla syrup.
Escribe sus métodos cost() y describe() preguntando primero a la bebida interna. El código proporcionado lee líneas como milk,syrup vanilla,sugar (una línea vacía representa un café simple) e imprime coffee + milk + vanilla syrup + sugar: 3.50.
Tu código va en Drink.R y Extras.R. main.R contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
source("Drink.R")
source("Extras.R")
# Código de entrada/salida suministrado: déjalo como está
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
d <- new_coffee()
if (nchar(line) > 0) for (extra in strsplit(line, ",")[[1]]) {
p <- strsplit(extra, " ")[[1]]
d <- switch(p[1], milk = add_milk(d), sugar = add_sugar(d), syrup = add_syrup(d, p[2]))
}
cat(sprintf("%s: %.2f", describe(d), cost(d)), "\n", sep = "")
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Fundamentos de S3
Trabajar con archivosListas con una claseFunciones constructorasMétodos de impresión y formatoValidadores y auxiliaresRepaso: temperaturas4Encapsulación en R
Cierres como objetosEntornos como objetosFunciones de accesoProtección del estadoRepaso: parquímetro2S3 Genéricos y métodos
Genéricos y UseMethodMétodos predeterminadosMétodos para genéricos baseFundamentos de NextMethodRepaso: áreas de figuras5Clases S4
Definición de clases S4Slots y accesoComprobaciones de validezMétodos showRepaso - Catálogo de productos8Clases de referencia
Definición de clases de referenciaMétodos y actualizaciones de camposSemántica de copiaHerencia y callSuperRepaso: cola de tareas11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de R online