Factory-Muster
Teil des Abschnitts Objektorientierte Programmierung der GDScript-Journey von Coddy. Lektion 47 von 65.
Das Factory-Muster verlagert die Entscheidung, welche Klasse erstellt werden soll, an eine zentrale Stelle. Der Rest des Programms fragt die Factory nach „einem Goblin“ und erhält ein Objekt zurück, ohne die Klasse Goblin zu benennen.
Die Produkte haben eine gemeinsame Elternklasse, daher funktioniert der Code, der sie verwendet, mit jedem von ihnen:
# enemy.gd
class_name Enemy
extends RefCounted
var hp := 10
func attack() -> String:
return "The enemy waits"# goblin.gd
class_name Goblin
extends Enemy
func attack() -> String:
return "The goblin stabs"# orc.gd
class_name Orc
extends Enemy
func attack() -> String:
return "The orc smashes"Die Fabrik ist eine Klasse mit einer static func, die einen Namen in ein Objekt umwandelt. Ihr Rückgabetyp ist die übergeordnete Klasse, sodass sie jede Art von Gegner zurückgeben kann oder null für einen Namen, den sie nicht kennt:
# enemy_factory.gd
class_name EnemyFactory
extends RefCounted
static func create(kind: String) -> Enemy:
match kind:
"goblin":
return Goblin.new()
"orc":
return Orc.new()
return null# main.gd
for kind in ["orc", "goblin", "slime"]:
var enemy := EnemyFactory.create(kind)
if enemy == null:
print("Unknown enemy: ", kind)
else:
print(enemy.attack())The orc smashes
The goblin stabs
Unknown enemy: slimeNamen wie diese stammen üblicherweise aus Daten: einer Spawn-Tabelle, einer Leveldatei oder einem Befehl, den der Spieler eingegeben hat. Die Factory ist der einzige Ort, der sie Klassen zuordnet. Um einen Dragon hinzuzufügen, braucht es also nur eine neue Datei und einen neuen Zweig in match.
Eine Factory kann das Objekt auch vorbereiten, bevor sie es zurückgibt, sodass jeder Aufrufer einen einsatzbereiten Gegner erhält:
static func create_boss(kind: String, level: int) -> Enemy:
var boss := create(kind)
if boss != null:
boss.hp = 100 * level
return bossEnemyFactory.create_boss("orc", 3) gibt einen Orc mit 300 HP zurück.
Aufgabe
MittelEine Spawn-Tabelle nennt Gegner und Level. Enemy (enemy.gd) und seine Unterklasse Goblin (goblin.gd) sind bereits geschrieben; vervollständige den Rest:
- In
orc.gdübergibt der Konstruktor_init(level)den NamenOrc,25 * levelHP und4 + levelSchaden an den Elternkonstruktor, so wie esGoblinmacht. - In
enemy_factory.gdgibtstatic func create(kind, level)einenGoblinfürgoblinund einenOrcfürorczurück, jeweils mit diesem Level erstellt. Groß- und Kleinschreibung im Namen spielt keine Rolle (ORCist ein Orc). Jeder andere Name gibtnullzurück.
Der bereitgestellte Code liest ein, wie viele Spawns folgen, dann eine Zeile mit KIND LEVEL pro Spawn, und gibt jeden Gegner oder Unknown enemy: KIND aus, gefolgt von der Anzahl der gespawnten Gegner. Für goblin 2, Orc 3 und slime 1 lautet die Ausgabe:
Goblin: 20 HP, 4 damage
Orc: 75 HP, 7 damage
Unknown enemy: slime
Spawned: 2Dein Code gehört in enemy_factory.gd und orc.gd. main.gd enthält den bereitgestellten Ein-/Ausgabecode und kann nicht bearbeitet werden.
Probier es selbst
extends Node
func _ready():
# Vorgegebener Eingabe-/Ausgabecode: Lass ihn unverändert
var spawned := 0
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
var enemy := EnemyFactory.create(parts[0], int(parts[1]))
if enemy == null:
print("Unknown enemy: ", parts[0])
else:
spawned += 1
print(enemy.describe())
print("Spawned: ", spawned)
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 – Formrechner2Klassenattribute
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