Menu
CoddyTech

Pattern Strategy

Fa parte della sezione Programmazione orientata agli oggetti del percorso GDScript di Coddy. Lezione 49 di 65.

Il pattern Strategy inserisce ogni versione di un algoritmo nel proprio oggetto, così puoi sostituire l’algoritmo mentre il programma è in esecuzione. L’oggetto che lo utilizza, il contesto, chiama un metodo e non gli importa quale versione contiene.

Ecco due strategie di attacco, una classe padre e una sottoclasse con lo stesso metodo damage():

# 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

Il contesto memorizza una strategia e le affida il calcolo:

# 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 non controlla mai quale stile usa. Un nuovo stile corrisponde a una nuova classe, mentre fighter.gd rimane così com'è; una catena if style == "heavy" all'interno di attack() crescerebbe con ogni stile.

Quando una strategia consiste in una piccola funzione senza dati propri, è sufficiente un Callable. Il contesto memorizza la funzione e la esegue con call():

# 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

Usa le classi quando una strategia ha impostazioni proprie o diversi metodi, e i Callable per un breve calcolo. Hai già usato questa idea: la funzione di confronto che passi a sort_custom() è una strategia di ordinamento.

challenge icon

Sfida

Medio

Un carrello può cambiare strategia di sconto al momento del pagamento. Discount in discount.gd è la strategia di base: nessuno sconto. Scrivi altre due strategie e il carrello:

  • PercentOff (creata con una percentuale): apply(total) restituisce total - total * percent / 100 (aritmetica intera), e label() restituisce 10% off per il 10 percento.
  • FixedOff (creata con un importo): apply(total) restituisce il totale meno l’importo, ma mai un valore inferiore a 0, e label() restituisce 30 off per un importo di 30.
  • Cart: set_discount(new_discount) memorizza la strategia e checkout() somma i prezzi e restituisce Subtotal TOTAL, LABEL, pay PRICE, dove PRICE è il valore restituito da apply() della strategia.

Il codice fornito legge i prezzi su una riga, il numero di pagamenti successivi e una strategia per riga: percent N, fixed N oppure none. Per i prezzi 50 30 40 e le strategie percent 10, fixed 30, none, l’output è:

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

Il tuo codice va inserito in cart.gd, percent_off.gd e fixed_off.gd. main.gd contiene il codice fornito per l’input/output e non può essere modificato.

Provalo tu

extends Node

func _ready():
	# Codice di input/output fornito: lascialo così com'è
	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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore GDScript online