Programming lesson
Entwurfsmuster in der Spieleentwicklung: Command, Factory und Memento am Beispiel von Fantastic World
Lerne, wie du mit Command, Abstract Factory und Memento ein erweiterbares RPG-System wie 'Fantastic World' entwirfst – inklusive Undo/Redo und Open-Closed Principle.
Einführung in die zeitgemäße Softwareentwicklung mit Entwurfsmustern
In der heutigen Spieleindustrie, in der Spiele wie Genshin Impact oder Honkai: Star Rail regelmäßig neue Charaktere und Fähigkeiten nachliefern, ist ein flexibles und erweiterbares Softwaredesign unerlässlich. Das Open-Closed Principle (OCP) besagt, dass Klassen offen für Erweiterungen, aber geschlossen für Modifikationen sein sollten. In diesem Tutorial zeigen wir dir, wie du dieses Prinzip mit den Entwurfsmustern Command, Abstract Factory und Memento in einem RPG-System wie Fantastic World umsetzt – ohne die gesamte Hausaufgabe zu lösen.
Projektkontext: Fantastic World – Ein RPG mit Heldenvielfalt
Stell dir vor, du entwickelst ein RPG, in dem Spieler verschiedene Helden wie Warrior (Fokus auf Verteidigung) und Warlock (Fokus auf Magieschaden) besitzen können. Zukünftig sollen Healer, Ranger und weitere Klassen hinzukommen. Das System muss folgende Funktionen bieten: Spieler erstellen, Helden hinzufügen/entfernen, Fähigkeiten einsetzen, Undo/Redo für bestimmte Aktionen und mehr. Genau hier kommen die Entwurfsmuster ins Spiel.
1. Command Pattern – Aktionen kapseln und rückgängig machen
Das Command Pattern wandelt einen Befehl in ein eigenständiges Objekt um. Das ermöglicht es, Befehle zu protokollieren, zu verzögern oder rückgängig zu machen. In Fantastic World wird jeder Benutzereingabe (z. B. „create player“, „add hero“, „call hero skill“) ein Command-Objekt zugeordnet.
Umsetzung in Java
public interface Command {
void execute();
void undo();
}
public class CreatePlayerCommand implements Command {
private Player player;
private Game game;
public CreatePlayerCommand(Game game, String id, String name) {
this.game = game;
this.player = new Player(id, name);
}
@Override
public void execute() {
game.addPlayer(player);
game.setCurrentPlayer(player);
}
@Override
public void undo() {
game.removePlayer(player.getId());
}
}Durch die Speicherung der Commands in einer Liste kann der Spieler mit Undo und Redo navigieren. Das Memento Pattern hilft dabei, den Zustand vor und nach einem Befehl zu sichern – besonders wichtig für „call hero skill“ und „change player’s name“.
2. Abstract Factory Pattern – Familien von Objekten erzeugen
Die Abstract Factory bietet eine Schnittstelle zur Erzeugung verwandter Objekte, ohne die konkreten Klassen zu nennen. In unserem RPG müssen wir Player, Warrior, Warlock und später Healer erzeugen können.
Beispiel: Factory für Helden
public interface HeroFactory {
Hero createHero(String id, String name);
}
public class WarriorFactory implements HeroFactory {
@Override
public Hero createHero(String id, String name) {
return new Warrior(id, name);
}
}
public class WarlockFactory implements HeroFactory {
@Override
public Hero createHero(String id, String name) {
return new Warlock(id, name);
}
}Durch die Kombination mit einer Abstract Factory für Commands wird das System extrem flexibel. Neue Heldentypen erfordern nur eine neue Factory und neue Command-Klassen – der bestehende Code bleibt unverändert.
3. Memento Pattern – Zustandssicherung für Undo/Redo
Das Memento Pattern speichert den internen Zustand eines Objekts, sodass er später wiederhergestellt werden kann. In Fantastic World wird es für die Funktionen „call hero skill“ und „change player’s name“ genutzt, da diese den Zustand des Helden oder Spielers verändern.
Implementierung
public class PlayerMemento {
private String name;
private List<Hero> heroes;
public PlayerMemento(String name, List<Hero> heroes) {
this.name = name;
this.heroes = new ArrayList<>(heroes);
}
public String getName() { return name; }
public List<Hero> getHeroes() { return heroes; }
}
public class Player {
private String id;
private String name;
private List<Hero> heroes;
public PlayerMemento save() {
return new PlayerMemento(name, heroes);
}
public void restore(PlayerMemento memento) {
this.name = memento.getName();
this.heroes = memento.getHeroes();
}
}Das Command-Objekt speichert vor der Ausführung ein Memento des aktuellen Zustands. Bei Undo wird der alte Zustand wiederhergestellt, bei Redo der neue.
4. Open-Closed Principle in der Praxis
Durch die Kombination der drei Muster bleibt das System offen für Erweiterungen. Ein neuer Heldentyp wie Healer erfordert nur:
- Eine neue Klasse
Healer(erbt vonHero) - Eine neue
HealerFactory(implementiertHeroFactory) - Gegebenenfalls neue Command-Klassen, falls der Healer eigene Aktionen hat
Der gesamte vorhandene Code – Spielerlogik, Undo/Redo-Mechanismus, Benutzeroberfläche – bleibt unverändert. Das entspricht exakt dem OCP.
5. Testplan und Testfälle – Qualitätssicherung
Ein guter Testplan deckt alle Funktionen ab. Hier ein Auszug für die Funktion „Add Hero“:
| Testfall | Eingabe | Erwartetes Ergebnis |
|---|---|---|
| TC-01: Warrior hinzufügen | H001, Peter, Typ 1 | Held wird dem aktuellen Spieler hinzugefügt |
| TC-02: Warlock hinzufügen | H002, John, Typ 2 | Held wird hinzugefügt |
| TC-03: Ungültiger Typ | H003, Anna, Typ 3 | Fehlermeldung |
Für Undo/Redo musst du sicherstellen, dass nach einem Undo der vorherige Zustand wiederhergestellt wird und nach Redo der neue Zustand erneut gilt.
Fazit und Ausblick
Die Entwurfsmuster Command, Abstract Factory und Memento sind ideale Werkzeuge, um ein erweiterbares RPG-System zu entwickeln. Sie fördern saubere Trennung von Verantwortlichkeiten, Wiederverwendbarkeit und Wartbarkeit. Mit diesen Mustern bist du bestens gerüstet, um auch komplexe Systeme wie Fantastic World zu meistern – und das ganz ohne harte Codierung. Probiere es selbst aus und erweitere das Spiel um einen Healer oder Ranger!