Menu
CoddyTech

Wzorzec dekoratora

Część sekcji Programowanie obiektowe ścieżki GDScript w Coddy. Lekcja 52 z 65.

Wzorzec Dekorator dodaje zachowanie do obiektu, opakowując go w inny obiekt z tymi samymi metodami. Każda otoczka wywołuje obiekt znajdujący się wewnątrz i dodaje własną część, a otoczki można nakładać na siebie w dowolnej kolejności.

# weapon.gd
class_name Weapon
extends RefCounted

func get_damage() -> int:
	return 10

func describe() -> String:
	return "Sword"

Dekorator rozszerza Weapon, więc można go użyć wszędzie tam, gdzie oczekiwana jest broń, i przechowuje owiniętą przez siebie broń:

# fire_enchant.gd
class_name FireEnchant
extends Weapon

var inner: Weapon

func _init(wrapped: Weapon) -> void:
	inner = wrapped

func get_damage() -> int:
	return inner.get_damage() + 5

func describe() -> String:
	return inner.describe() + " + Fire"

SharpEnchant jest zapisany w ten sam sposób, ale jego get_damage() zwraca inner.get_damage() * 2, a jego describe() dodaje " + Sharp".

# main.gd
var weapon: Weapon = Weapon.new()
print(weapon.describe(), ": ", weapon.get_damage())
weapon = FireEnchant.new(weapon)
weapon = SharpEnchant.new(weapon)
print(weapon.describe(), ": ", weapon.get_damage())
Sword: 10
Sword + Fire + Sharp: 30

Wywołania biegną do wewnątrz: SharpEnchant pyta FireEnchant, który pyta miecz. Miecz zwraca 10, ogień zwiększa tę wartość do 15, a Sharp podwaja ją do 30. W odwrotnej kolejności, FireEnchant.new(SharpEnchant.new(Weapon.new())), obrażenia wynoszą 10 * 2 + 5, czyli 25.

Bez dekoratorów każda kombinacja wymagałaby własnej podklasy: FireSword, SharpSword, FireSharpSword i tak dalej. Dzięki nim dwie małe klasy obsługują każdą kombinację, a nowe zaklęcie to kolejny plik.

challenge icon

Wyzwanie

Średni

Kawiarnia przygotowuje napoje za pomocą dekoratorów. Beverage (beverage.gd) deklaruje cost() i description(); Espresso (espresso.gd, $3) i Tea (tea.gd, $2) są już napisane. Każdy dekorator przechowuje napój, który opakowuje, w inner (konstruktory są już napisane). Nadpisz cost() i description() w:

  • Milk: kosztuje o 1 więcej i dodaje + Milk do opisu.
  • Mocha: kosztuje o 2 więcej i dodaje + Mocha.
  • Large: podwaja koszt wszystkiego, co się w nim znajduje, i umieszcza Large na początku opisu.

Dostarczony kod odczytuje liczbę kolejnych zamówień, a następnie jedno zamówienie w każdym wierszu: napój (espresso lub tea) i dodatki, stosowane od lewej do prawej. Dla espresso milk large i tea mocha milk wynik to:

Large Espresso + Milk: $8
Tea + Mocha + Milk: $5

Twój kod umieść w plikach milk.gd, mocha.gd i large.gd. main.gd zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

extends Node

func _ready():
	# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var words := OS.read_string_from_stdin().split(" ")
		var drink: Beverage = Tea.new()
		if words[0] == "espresso":
			drink = Espresso.new()
		for extra in words.slice(1):
			match extra:
				"milk":
					drink = Milk.new(drink)
				"mocha":
					drink = Mocha.new(drink)
				"large":
					drink = Large.new(drink)
		print("%s: $%d" % [drink.description(), drink.cost()])
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator GDScript online