Menu
CoddyTech

Strategy Deseni

Coddy'nin GDScript Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 49 / 65.

Strategy kalıbı, bir algoritmanın her sürümünü kendi nesnesine koyar; böylece program çalışırken algoritmayı değiştirebilirsin. Algoritmayı kullanan nesneye bağlam denir. Bağlam tek bir yöntemi çağırır ve hangi sürümü barındırdığını önemsemez.

İşte iki saldırı stratejisi: aynı damage() metoduna sahip bir üst sınıf ve bir alt sınıf:

# attack_style.gd
class_name AttackStyle
extends RefCounted

func damage(power: int) -> int:
	return power
# heavy_attack.gd
class_name HeavyAttack
extends AttackStyle

func damage(power: int) -> int:
	return power * 2

Bağlam bir strateji depolar ve hesaplamayı ona devreder:

# fighter.gd
class_name Fighter
extends RefCounted

var power := 10
var style: AttackStyle = AttackStyle.new()

func set_style(new_style: AttackStyle) -> void:
	style = new_style

func attack() -> void:
	print("Hit for ", style.damage(power))
# main.gd
var fighter := Fighter.new()
fighter.attack()
fighter.set_style(HeavyAttack.new())
fighter.attack()
Hit for 10
Hit for 20

Fighter hangi dövüş stiline sahip olduğunu asla kontrol etmez. Yeni bir stil, yeni bir sınıftır ve fighter.gd olduğu gibi kalır; attack() içindeki if style == "heavy" zinciri her stille birlikte büyürdü.

Bir strateji, kendi verisi olmayan küçük bir işlevden ibaretse Callable yeterlidir. Bağlam, işlevi saklar ve onu call() ile çalıştırır:

# price_calculator.gd
class_name PriceCalculator
extends RefCounted

var discount: Callable = func(price): return price

func final_price(price: int) -> int:
	return discount.call(price)
# main.gd
var calc := PriceCalculator.new()
print(calc.final_price(80))
calc.discount = func(price): return price / 2
print(calc.final_price(80))
calc.discount = func(price): return max(price - 25, 0)
print(calc.final_price(80))
80
40
55

Bir stratejinin kendi ayarları veya birden fazla yöntemi varsa sınıfları, tek bir kısa hesaplama içinse Callable'ları kullan. Bu fikri daha önce kullandın: sort_custom() işlevine aktardığın karşılaştırma işlevi bir sıralama stratejisidir.

challenge icon

Görev

Orta

Bir alışveriş sepeti, ödeme sırasında indirim stratejilerini değiştirebilir. discount.gd içindeki Discount, temel stratejidir: indirim yok. İki strateji daha ve sepeti yaz:

  • PercentOff (yüzdeyle oluşturulur): apply(total), total - total * percent / 100 değerini döndürür (tamsayı aritmetiği) ve label(), yüzde 10 için 10% off değerini döndürür.
  • FixedOff (bir tutarla oluşturulur): apply(total), toplamdan tutarı çıkarır ancak hiçbir zaman 0 değerinin altına düşmez ve label(), 30 tutarı için 30 off değerini döndürür.
  • Cart: set_discount(new_discount) stratejiyi saklar ve checkout() fiyatları toplar ve PRICE, stratejinin apply() metodunun döndürdüğü değer olmak üzere Subtotal TOTAL, LABEL, pay PRICE değerini döndürür.

Sağlanan kod, fiyatları bir satırda, sonraki ödeme sayısını ve her satırda bir stratejiyi okur: percent N, fixed N veya none. 50 30 40 fiyatları ve percent 10, fixed 30, none stratejileri için çıktı şöyledir:

Subtotal 120, 10% off, pay 108
Subtotal 120, 30 off, pay 90
Subtotal 120, no discount, pay 120

Kodunu cart.gd, percent_off.gd ve fixed_off.gd dosyalarına yaz. main.gd, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

extends Node

func _ready():
	# Sağlanan giriş/çıkış kodu: olduğu gibi bırakın
	var cart := Cart.new()
	for price in OS.read_string_from_stdin().split(" "):
		cart.add_item(int(price))
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		if parts[0] == "percent":
			cart.set_discount(PercentOff.new(int(parts[1])))
		elif parts[0] == "fixed":
			cart.set_discount(FixedOff.new(int(parts[1])))
		else:
			cart.set_discount(Discount.new())
		print(cart.checkout())
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online GDScript derleyicisi