Padrão Decorator
Parte da seção Programação Orientada a Objetos do Journey de R da Coddy. Lição 46 de 57.
Um decorator envolve algo e adiciona comportamento, mantendo a mesma interface. Para uma função, o decorator recebe uma função e retorna uma nova função que realiza trabalho adicional em torno da chamada:
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))Saída:
calling double with 21
[1] 42Um decorador pode lembrar resultados. with_cache() mantém cada resposta em um ambiente e chama a função envolvida apenas para novos argumentos:
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)Saída:
results computed: 2Objetos também podem ser decorados. Cada decorador é um objeto que mantém o objeto que ele envolve em um campo e responde aos mesmos genéricos, adicionando sua parte e pedindo o restante ao objeto interno:
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))Saída:
coffee + milk + milk = 3Os decoradores são empilhados, e a ordem deles importa: o mais externo é executado primeiro na entrada e por último na saída:
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"))Saída:
hi ada! hi ada! / hi ada hi ada!Desafio
FácilAs bebidas são decoradas com extras. Drink.R contém os genéricos cost() e describe() e a bebida base, new_coffee(), que custa 2 e se descreve como coffee. Em Extras.R, escreva três decoradores, cada um sendo um objeto que armazena a bebida que envolve no campo inner:
add_milk(d): classemilk, adiciona 0.50 e+ milk;add_sugar(d): classesugar, adiciona 0.20 e+ sugar;add_syrup(d, flavour): classesyrupcom o campoflavour, adiciona 0.80 e+ vanilla syrup.
Escreva os métodos cost() e describe() deles consultando primeiro a bebida interna. O código fornecido lê linhas como milk,syrup vanilla,sugar (uma linha vazia representa um café simples) e imprime coffee + milk + vanilla syrup + sugar: 3.50.
Seu código deve estar em Drink.R e Extras.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
source("Drink.R")
source("Extras.R")
# Código de entrada/saída fornecido: mantenha-o 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 lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos do S3
Trabalhando com ArquivosListas com uma ClasseFunções ConstrutorasMétodos de Impressão e FormataçãoValidadores e AuxiliaresRevisão - Temperaturas4Encapsulamento em R
Closures como ObjetosAmbientes como ObjetosFunções de AcessoProtegendo o EstadoRecapitulação - Parquímetro2Genéricos e Métodos S3
Genéricos e UseMethodMétodos padrãoMétodos para genéricos baseFundamentos de NextMethodRevisão - Áreas de formas5Classes S4
Definindo classes S4Slots e acessoVerificações de validadeMétodos showRevisão - Catálogo de produtos8Classes de Referência
Definindo Classes de ReferênciaMétodos e Atualizações de CamposSemântica de CópiaHerança e callSuperRecapitulação — Fila de Tarefas11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Compilador de R online