Шаблон Strategy
Часть раздела Объектно-ориентированное программирование путешествия по R на Coddy. Урок 45 из 57.
Паттерн стратегия делает алгоритм заменяемым: код, которому он нужен, получает его в качестве аргумента. В R функция является значением, поэтому стратегия представляет собой передаваемую функцию, а вызывающий код выбирает, какую именно:
no_discount <- function(total) total
half_price <- function(total) total / 2
checkout <- function(total, discount = no_discount) {
paste("pay", discount(total))
}
print(checkout(80))
print(checkout(80, half_price))Вывод:
[1] "pay 80"
[1] "pay 40"Именованный список стратегий позволяет программе выбирать одну из них по имени во время выполнения, например из пользовательского ввода:
pricing <- list(
regular = function(p) p,
member = function(p) p * 0.9,
staff = function(p) p * 0.7
)
for (who in c("regular", "member", "staff")) cat(who, pricing[[who]](50), "\n")Результат:
regular 50
member 45
staff 35 Стратегии с настройками создаются фабриками. percent_off(10) возвращает новую функцию-стратегию, которая запоминает свой процент:
percent_off <- function(pct) function(total) total * (1 - pct / 100)
fixed_off <- function(amount) function(total) max(0, total - amount)
rules <- list(percent_off(10), percent_off(25), fixed_off(30))
print(vapply(rules, function(r) r(100), numeric(1)))Результат:
[1] 90 75 70Объект может хранить свою стратегию в поле и позже заменять её. Остальная часть объекта остаётся неизменной:
new_sorter <- function(key) structure(list(key = key), class = "sorter")
sort_with <- function(s, words) words[order(s$key(words))]
by_length <- function(w) nchar(w)
by_last_letter <- function(w) substring(w, nchar(w))
s <- new_sorter(by_length)
words <- c("pear", "fig", "banana")
print(sort_with(s, words))
s$key <- by_last_letter
print(sort_with(s, words))Результат:
[1] "fig" "pear" "banana"
[1] "banana" "fig" "pear" Задание
ЛегкоСтоимость доставки выбирается стратегией: функцией от общего веса корзины и её промежуточной суммы, которая возвращает стоимость доставки. В Strategies.R напишите:
standard(kg, subtotal): 4.99 плюс 1 за каждый кг;express(kg, subtotal): вдвое дороже стандартной стоимости;free_over(limit): возвращает стратегию, стоимость которой равна 0, если промежуточная сумма не меньшеlimit, и стандартной стоимости в противном случае.
В Cart.R функции new_cart(strategy) и add_item() уже предоставлены; завершите реализацию subtotal(cart) и shipping_cost(cart), которая вызывает стратегию корзины. Предоставленный код считывает стратегию (standard, express или free_over 50), затем товары book 12 0.5 (название, цена, кг) и выводит итоговые суммы.
Ваш код должен находиться в Strategies.R и Cart.R. В main.R находится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
source("Strategies.R")
source("Cart.R")
# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
p <- strsplit(input[1], " ")[[1]]
rule <- if (p[1] == "free_over") free_over(as.numeric(p[2])) else get(p[1])
cart <- new_cart(rule)
for (line in input[-1]) {
q <- strsplit(line, " ")[[1]]
cart <- add_item(cart, q[1], as.numeric(q[2]), as.numeric(q[3]))
}
cat(sprintf("items: %.2f, shipping: %.2f, total: %.2f", subtotal(cart), shipping_cost(cart), subtotal(cart) + shipping_cost(cart)), "\n", sep = "")
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы S3
Работа с файламиСписки с классомФункции-конструкторыМетоды print и formatВалидаторы и вспомогательные функцииПовторение — температуры4Инкапсуляция в R
Замыкания как объектыОкружения как объектыФункции доступаЗащита состоянияПовторение — парковочный счётчик7S4 Наследование
Расширение с помощью containscallNextMethodВиртуальные классыПроверка типов с помощью is()Повторение — смотритель зоопарка10Шаблоны проектирования, часть 2
Шаблон «Декоратор»Шаблон «Строитель»Шаблон «Состояние»Шаблон «Итератор»2Обобщённые функции и методы S3
Обобщённые функции и UseMethodМетоды по умолчаниюМетоды для базовых обобщённых функцийОсновы NextMethodПовторение — площади фигур5Классы S4
Определение классов S4Слоты и доступПроверка корректностиМетоды showПовторение — каталог товаров8Ссылочные классы
Определение ссылочных классовМетоды и обновление полейСемантика копированияНаследование и callSuperПовторение — очередь задач11Проект: Управление библиотекой
Книги и читателиВыдача книг3Наследование S3
Векторы классовПорядок поиска методовРасширение с помощью NextMethodПроверка с помощью inherits()Повторение — расчёт зарплаты сотрудниковПотренируйтесь самостоятельно: Онлайн-компилятор R