Implementieren einfacher Zustandsmaschinen mit Java-Aufzählungen

1. Übersicht

In diesem Tutorial sehen wir uns State Machines an und wie sie mithilfe von Enums in Java implementiert werden können.

Wir werden auch die Vorteile dieser Implementierung im Vergleich zur Verwendung einer Schnittstelle und einer konkreten Klasse für jeden Zustand erläutern.

2. Java-Aufzählungen

Eine Java-Aufzählung ist ein spezieller Klassentyp, der eine Liste von Konstanten definiert. Dies ermöglicht eine typsichere Implementierung und besser lesbaren Code .

Nehmen wir als Beispiel an, wir haben ein HR-Softwaresystem, das von Mitarbeitern eingereichte Urlaubsanträge genehmigen kann. Diese Anfrage wird vom Teamleiter geprüft, der sie an den Abteilungsleiter weiterleitet. Der Abteilungsleiter ist für die Genehmigung der Anfrage verantwortlich.

Die einfachste Aufzählung, die die Zustände eines Urlaubsantrags enthält, ist:

public enum LeaveRequestState { Submitted, Escalated, Approved }

Wir können uns auf die Konstanten dieser Aufzählung beziehen:

LeaveRequestState state = LeaveRequestState.Submitted;

Aufzählungen können auch Methoden enthalten. Wir können eine abstrakte Methode in eine Aufzählung schreiben, die jede Aufzählungsinstanz zwingt, diese Methode zu implementieren. Dies ist sehr wichtig für die Implementierung von Zustandsautomaten, wie wir weiter unten sehen werden.

Da Java-Aufzählungen die Klasse java.lang.Enum implizit erweitern , können sie keine andere Klasse erweitern. Sie können jedoch wie jede andere Klasse eine Schnittstelle implementieren.

Hier ist ein Beispiel für eine Aufzählung mit einer abstrakten Methode:

public enum LeaveRequestState { Submitted { @Override public String responsiblePerson() { return "Employee"; } }, Escalated { @Override public String responsiblePerson() { return "Team Leader"; } }, Approved { @Override public String responsiblePerson() { return "Department Manager"; } }; public abstract String responsiblePerson(); }

Beachten Sie die Verwendung des Semikolons am Ende der letzten Aufzählungskonstante. Das Semikolon ist erforderlich, wenn eine oder mehrere Methoden den Konstanten folgen.

In diesem Fall haben wir das erste Beispiel um eine ResponsiblePerson () -Methode erweitert. Dies teilt uns die Person mit, die für die Ausführung jeder Aktion verantwortlich ist. Wenn wir also versuchen, die Person zu überprüfen, die für den eskalierten Zustand verantwortlich ist, erhalten wir den „Teamleiter“:

LeaveRequestState state = LeaveRequestState.Escalated; assertEquals("Team Leader", state.responsiblePerson());

Wenn wir überprüfen, wer für die Genehmigung der Anfrage verantwortlich ist, erhalten wir auf die gleiche Weise den „Abteilungsleiter“:

LeaveRequestState state = LeaveRequestState.Approved; assertEquals("Department Manager", state.responsiblePerson());

3. Zustandsmaschinen

Eine Zustandsmaschine - auch als endliche Zustandsmaschine oder endlicher Automat bezeichnet - ist ein Rechenmodell, das zum Erstellen einer abstrakten Maschine verwendet wird. Diese Maschinen können sich jeweils nur in einem Zustand befinden. Jeder Status ist ein Status des Systems, der in einen anderen Status wechselt. Diese Zustandsänderungen werden als Übergänge bezeichnet.

In der Mathematik kann es mit Diagrammen und Notationen kompliziert werden, aber für uns Programmierer ist es viel einfacher.

Das State Pattern ist eines der bekanntesten 23 Designmuster des GoF. Dieses Muster entlehnt das Konzept dem Modell in der Mathematik. Es ermöglicht einem Objekt, je nach Status unterschiedliche Verhaltensweisen für dasselbe Objekt zu kapseln. Wir können den Übergang zwischen Zuständen programmieren und später separate Zustände definieren.

Um das Konzept besser zu erläutern, erweitern wir unser Beispiel für Urlaubsanträge, um eine Zustandsmaschine zu implementieren.

4. Aufzählungen als Zustandsmaschinen

Wir werden uns auf die Enum-Implementierung von Zustandsautomaten in Java konzentrieren. Andere Implementierungen sind möglich und werden im nächsten Abschnitt verglichen.

Der Hauptpunkt der Implementierung der Zustandsmaschine unter Verwendung einer Aufzählung ist, dass wir uns nicht mit dem expliziten Festlegen der Zustände befassen müssen . Stattdessen können wir nur die Logik für den Übergang von einem Zustand zum nächsten bereitstellen. Lassen Sie uns gleich eintauchen:

public enum LeaveRequestState { Submitted { @Override public LeaveRequestState nextState() { return Escalated; } @Override public String responsiblePerson() { return "Employee"; } }, Escalated { @Override public LeaveRequestState nextState() { return Approved; } @Override public String responsiblePerson() { return "Team Leader"; } }, Approved { @Override public LeaveRequestState nextState() { return this; } @Override public String responsiblePerson() { return "Department Manager"; } }; public abstract LeaveRequestState nextState(); public abstract String responsiblePerson(); }

In diesem Beispiel werden die Zustandsmaschinenübergänge mithilfe der abstrakten Methoden der Aufzählung implementiert . Genauer gesagt geben wir mit dem nextState () für jede Enum-Konstante den Übergang zum nächsten Zustand an. Bei Bedarf können wir auch eine previousState () -Methode implementieren .

Nachfolgend finden Sie einen Test zur Überprüfung unserer Implementierung:

LeaveRequestState state = LeaveRequestState.Submitted; state = state.nextState(); assertEquals(LeaveRequestState.Escalated, state); state = state.nextState(); assertEquals(LeaveRequestState.Approved, state); state = state.nextState(); assertEquals(LeaveRequestState.Approved, state);

Wir beginnen den Urlaubsantrag im Übermittelt Ausgangszustand zurück . Anschließend überprüfen wir die Statusübergänge mithilfe der oben implementierten nextState () -Methode.

Beachten Sie, dass kein anderer Übergang stattfinden kann , da Genehmigt der Endzustand ist .

5. Vorteile der Implementierung von State Machines mit Java Enums

Die Implementierung von Zustandsautomaten mit Schnittstellen und Implementierungsklassen kann eine erhebliche Menge an Code sein, die entwickelt und gewartet werden muss.

Da eine Java-Aufzählung in ihrer einfachsten Form eine Liste von Konstanten ist, können wir eine Aufzählung verwenden, um unsere Zustände zu definieren. Und da eine Aufzählung auch Verhalten enthalten kann, können wir Methoden verwenden, um die Übergangsimplementierung zwischen Zuständen bereitzustellen.

Die gesamte Logik in einer einfachen Aufzählung zu haben, ermöglicht eine saubere und unkomplizierte Lösung.

6. Fazit

In diesem Artikel haben wir uns mit Zustandsautomaten befasst und wie sie mithilfe von Enums in Java implementiert werden können. Wir haben ein Beispiel gegeben und es getestet.

Schließlich haben wir auch die Vorteile der Verwendung von Enums zur Implementierung von Zustandsmaschinen erörtert. Als Alternative zur Schnittstellen- und Implementierungslösung bieten Aufzählungen eine sauberere und verständlichere Implementierung von Zustandsautomaten.

Wie immer finden Sie alle in diesem Artikel erwähnten Codefragmente in unserem GitHub-Repository.