Menu
CoddyTech

Adapter-Muster

Teil des Abschnitts Objektorientierte Programmierung der GDScript-Journey von Coddy. Lektion 51 von 65.

Das Adapter-Muster ermöglicht es einem Objekt, mit Code zusammenzuarbeiten, der andere Methoden erwartet. Der Adapter umschließt das Objekt und wandelt jeden erwarteten Aufruf in einen Aufruf um, den das Objekt versteht.

Eine alte Klasse aus einem früheren Projekt speichert die Gesundheit als zwei Zahlen:

# old_monster.gd
class_name OldMonster
extends RefCounted

var life := 30
var max_life := 120

Dein HUD zeigt alles an, was get_label() und get_hp_percent() hat. Ein Knight hat bereits beides (es gibt "Knight" und 80 zurück), aber OldMonster hat keines von beiden:

# health_display.gd
class_name HealthDisplay
extends RefCounted

func show_health(target) -> void:
	print(target.get_label(), ": ", target.get_hp_percent(), "%")

Der Adapter enthält ein OldMonster und stellt die beiden Methoden bereit, die die Anzeige aufruft:

# monster_adapter.gd
class_name MonsterAdapter
extends RefCounted

var monster: OldMonster

func _init(wrapped: OldMonster) -> void:
	monster = wrapped

func get_label() -> String:
	return "Monster"

func get_hp_percent() -> int:
	return monster.life * 100 / monster.max_life
# main.gd
var display := HealthDisplay.new()
display.show_health(Knight.new())
display.show_health(MonsterAdapter.new(OldMonster.new()))
Knight: 80%
Monster: 25%

Weder OldMonster noch HealthDisplay haben sich geändert. Das ist wichtig, wenn du eine Klasse nicht bearbeiten kannst oder solltest: Sie stammt aus einem Plugin, ein anderes Team ist dafür verantwortlich oder viele Skripte hängen von ihren Namen ab.

Der Adapter leitet jeden Aufruf weiter und wandelt dabei die Daten um, hier zwei Zahlen in einen Prozentwert. Multipliziere vor dem Dividieren: Bei Ganzzahlen ergibt 30 / 120 * 100 den Wert 0, während 30 * 100 / 120 den Wert 25 ergibt.

challenge icon

Aufgabe

Einfach

Eine Wetterstation zeigt Sensoren an, die über get_sensor_name() und get_celsius() verfügen, wie ModernSensor (modern_sensor.gd). Die Wetterstation befindet sich in weather_board.gd. Alte Thermometer (legacy_thermometer.gd) bieten nur read_fahrenheit() und get_code(). Schreibe den Adapter ThermometerAdapter:

  • Der Konstruktor speichert das umschlossene LegacyThermometer.
  • get_sensor_name() gibt Thermometer, ein Leerzeichen und den Code des Thermometers zurück, zum Beispiel Thermometer TH-4.
  • get_celsius() gibt die Temperatur in Celsius als float zurück: (fahrenheit - 32) * 5 / 9.

Ändere die anderen Klassen nicht. Der bereitgestellte Code liest ein, wie viele Sensoren folgen, dann einen pro Zeile: legacy ID FAHRENHEIT oder modern NAME CELSIUS. Er umschließt jedes alte Thermometer mit deinem Adapter und zeigt alle Sensoren an. Für legacy 4 98.6 und modern Garden 21.5 lautet die Ausgabe:

Thermometer TH-4: 37.0 C
Garden: 21.5 C
Warmest: Thermometer TH-4

Dein Code gehört in thermometer_adapter.gd. main.gd enthält den bereitgestellten Ein-/Ausgabecode und kann nicht bearbeitet werden.

Probier es selbst

extends Node

func _ready():
	# Vorgegebener Ein-/Ausgabecode: unverändert lassen
	var board := WeatherBoard.new()
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		if parts[0] == "legacy":
			var old := LegacyThermometer.new(int(parts[1]), float(parts[2]))
			board.add_sensor(ThermometerAdapter.new(old))
		else:
			board.add_sensor(ModernSensor.new(parts[1], float(parts[2])))
	board.show_all()
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-GDScript-Compiler