Menu
CoddyTech

Padrão Strategy

Parte da seção Programação orientada a objetos do Journey de GDScript da Coddy. Lição 49 de 65.

O padrão Strategy coloca cada versão de um algoritmo em seu próprio objeto, para que você possa trocar o algoritmo enquanto o programa está em execução. O objeto que o utiliza, o contexto, chama um método e não se importa com qual versão está usando.

Aqui estão duas estratégias de ataque, uma classe pai e uma subclasse com o mesmo método 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

O contexto armazena uma estratégia e delega o cálculo a ela:

# 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 nunca verifica qual estilo possui. Um novo estilo é uma nova classe, e fighter.gd permanece como está; uma cadeia de if style == "heavy" dentro de attack() cresceria a cada estilo.

Quando uma estratégia é uma pequena função sem dados próprios, um Callable é suficiente. O contexto armazena a função e a executa com 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

Use classes quando uma estratégia tiver suas próprias configurações ou vários métodos, e Callables para um cálculo curto. Você já usou essa ideia antes: a função de comparação que você passa para sort_custom() é uma estratégia de ordenação.

challenge icon

Desafio

Médio

Um carrinho de compras pode alternar entre estratégias de desconto no checkout. Discount em discount.gd é a estratégia base: sem desconto. Escreva mais duas e o carrinho:

  • PercentOff (criado com uma porcentagem): apply(total) retorna total - total * percent / 100 (aritmética inteira), e label() retorna 10% off para 10 por cento.
  • FixedOff (criado com um valor): apply(total) retorna o total menos o valor, mas nunca abaixo de 0, e label() retorna 30 off para um valor de 30.
  • Cart: set_discount(new_discount) armazena a estratégia, e checkout() soma os preços e retorna Subtotal TOTAL, LABEL, pay PRICE, em que PRICE é o valor retornado por apply() da estratégia.

O código fornecido lê os preços em uma linha, quantos checkouts vêm a seguir e uma estratégia por linha: percent N, fixed N ou none. Para os preços 50 30 40 e as estratégias percent 10, fixed 30, none, a saída é:

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

Seu código deve ficar em cart.gd, percent_off.gd e fixed_off.gd. main.gd contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

extends Node

func _ready():
	# Código de entrada/saída fornecido: mantenha-o como está
	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 iconTeste seus conhecimentos

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

Pratique por conta própria: Compilador de GDScript online