نمط 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
التعامل مع الملفاتالقوائم باستخدام فئةدوال المُنشئأساليب الطباعة والتنسيقأدوات التحقق والمساعدةمراجعة - درجات الحرارة2S3 الدوال العامة والطرق
الدوال العامة وUseMethodالطرق الافتراضيةطرق الدوال العامة الأساسيةأساسيات NextMethodمراجعة - مساحات الأشكالتدرّب بنفسك: مترجم R عبر الإنترنت