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 := 120Dein 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.
Aufgabe
EinfachEine 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()gibtThermometer, ein Leerzeichen und den Code des Thermometers zurück, zum BeispielThermometer TH-4.get_celsius()gibt die Temperatur in Celsius alsfloatzurü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-4Dein 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()
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort selfMethodenEigenschaftenKonstruktor (_init)Wiederholung – Einfacher Taschenrechner4Polymorphie
Methodenüberschreibung erneut betrachtetDuck-TypisierungAbstrakte Klassen und MethodenSchnittstellendesignRückblick – Formrechner7Signale
Was ist ein Signal?Deklarieren und AuslösenMit Signalen verbindenSignale mit ArgumentenRückblick – Gesundheitssystem10Entwurfsmuster Teil 2
Befehl-MusterAdapter-MusterDekorierer-MusterVorlagenmethoden-MusterZustandsmusterKompositum-Muster2Klassenattribute
Instanz- vs. statische VariablenStatische FunktionenProperty-SetterProperty-GetterPrivat nach KonventionWiederholung – Bankkontenverwaltung5Kapselung
Öffentliche und private MemberValidierung mit SetternInformationsverbergenSchreibgeschützte EigenschaftenRückblick – System zur Schülerverwaltung8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungInnere KlassenNodes als KomponentenRefCounted vs. NodeEnums in Klassen11Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungVererbungskettenTypprüfungen mit isWiederholung – Mitarbeiterhierarchie6Spezielle Methoden
Einführung in virtuelle MethodenDie _to_string-MethodeBenutzerdefinierte IteratorenRückblick – Benutzerdefinierte Liste9Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterBeobachter-MusterStrategie-Muster12Abschließende Herausforderungen
E-Learning-PlattformBankensystemEntwicklung von SpielfigurenFahrzeugvermietungÜbe selbstständig: Online-GDScript-Compiler