Zustands-Muster

Beim State-Muster ändert sich das Verhalten einer Klasse basierend auf ihrem Zustand. Diese Art von Entwurfsmuster gehört zu den Verhaltensmustern.

Beim State-Muster erstellen wir Objekte, die verschiedene Zustände repräsentieren, und ein Kontextobjekt, dessen Verhalten sich ändert, wenn sich das Zustandsobjekt ändert.

Das State-Muster ermöglicht es einem Objekt, sein Verhalten zu ändern, wenn sich sein interner Zustand ändert, sodass das Objekt in verschiedenen Zuständen unterschiedliche Verhaltensweisen zeigt. Indem jeder Zustand als unabhängige Klasse gekapselt wird, wird die Verwendung einer großen Anzahl von bedingten Anweisungen zur Implementierung der Zustandsumschaltung vermieden.

Einführung

Absicht

Es ermöglicht einem Objekt, sein Verhalten zu ändern, wenn sich sein interner Zustand ändert, sodass es erscheint, als hätte das Objekt seine Klasse geändert.

Wesentliche gelöste Probleme

  • Das State-Muster löst das Problem, dass das Verhalten eines Objekts von seinem Zustand abhängt, und ermöglicht dem Objekt, das Verhalten zu wechseln, wenn sich der Zustand ändert.

Anwendungsfall

  • Verwenden Sie es, wenn es viele bedingte Anweisungen im Code gibt und diese bedingten Anweisungen vom Zustand des Objekts abhängen.

Implementierungsansatz

  • Definieren Sie die Zustandsschnittstelle: Deklariert eine oder mehrere Methoden, um das Verhalten eines bestimmten Zustands zu kapseln.
  • Erstellen Sie konkrete Zustandsklassen: Implementiert die Zustandsschnittstelle und implementiert spezifische Verhaltensweisen basierend auf unterschiedlichen Zuständen.
  • Definieren Sie die Kontextklasse: Enthält eine Referenz auf ein Zustandsobjekt und aktualisiert ihr Verhalten, wenn sich der Zustand ändert.

Schlüsselcode

  • Zustandsschnittstelle: Deklariert Verhaltensmethoden.
  • Konkrete Zustandsklasse: Implementiert die Zustandsschnittstelle und kapselt spezifisches Verhalten.
  • Kontextklasse: Verwaltet ein Zustandsobjekt und stellt Methoden zum Ändern seines Zustands bereit.

Anwendungsbeispiel

  • Zustand eines Basketballspielers: Ein Athlet kann Zustände wie normal, abnormal und außergewöhnlich haben.
  • Glockenspiel des Markgrafen Yi von Zeng: Glockenspiele dienen als Kontext, und verschiedene Glocken (Zustände) erzeugen unterschiedliche Aufführungseffekte.

Vorteile

  • Kapselt Regeln für Zustandsübergänge: Kapselt die Logik für Zustandsübergänge in Zustandsobjekten.
  • Leicht zu erweitern: Das Hinzufügen neuer Zustandsklassen wirkt sich nicht auf vorhandenen Code aus.
  • Zustandsbezogenes Verhalten zentralisieren: Konzentriert das gesamte Verhalten, das sich auf einen bestimmten Zustand bezieht, in einer Klasse.
  • Bedingte Anweisungen vereinfachen: Vermeidet die Verwendung einer großen Anzahl bedingter Anweisungen, um Verhalten zu wechseln.
  • Teilen von Zuständen: Ermöglicht mehreren Kontextobjekten, dasselbe Zustandsobjekt zu teilen.

Nachteile

  • Erhöht die Anzahl der Klassen und Objekte: Jeder Zustand erfordert eine konkrete Zustandsklasse.
  • Komplexe Implementierung: Die Musterstruktur und die Implementierung sind relativ komplex.
  • Unzureichende Unterstützung für das Open-Closed-Prinzip: Das Hinzufügen neuer Zustände oder das Ändern des Zustandsverhaltens kann Änderungen am vorhandenen Code erfordern.

Verwendungshinweise

  • Wenn sich das Verhalten eines Objekts mit seinem Zustand ändert, sollte die Verwendung des Zustandsmusters in Betracht gezogen werden.
  • Das Zustandsmuster eignet sich zum Ersetzen komplexer bedingter oder Verzweigungsanweisungen.

Hinweise

  • Das State-Muster eignet sich, wenn die Anzahl der Zustände begrenzt ist (normalerweise nicht mehr als 5).
  • Mit Vorsicht verwenden, um zu vermeiden, dass das System übermäßig komplex wird.

Struktur

Das State-Muster umfasst die folgenden Hauptrollen:

  • Context: Definiert die Schnittstelle, an der Clients interessiert sind, und verwaltet eine Referenz auf das aktuelle Zustandsobjekt. Der Kontext kann die Verarbeitung zustandsbezogenen Verhaltens an das Zustandsobjekt delegieren.

  • State: Definiert eine Schnittstelle zum Kapseln des Verhaltens eines Zustands, der mit dem Kontext zusammenhängt.

  • Concrete State: Implementiert die Zustandsschnittstelle und ist für die Handhabung von Verhalten verantwortlich, das mit diesem Zustand zusammenhängt. Ein konkretes Zustandsobjekt verwaltet normalerweise intern eine Referenz auf das Kontextobjekt, sodass es je nach unterschiedlichen Bedingungen zu verschiedenen Zuständen wechseln kann.

Implementierung

Wir werden eineStateSchnittstelle und ImplementierungStatedie Entity-State-Klasse der Schnittstelle erstellen.ContextEine Klasse mit einem bestimmten Zustand.

StatePatternDemo, unsere Demo-Klasse verwendetContextund Zustandsobjekte, um zu demonstrieren, wie sich das Verhalten von Context ändert, wenn sich sein Zustand ändert.

状态模式的 UML 图

Schritt 1

Erstellen Sie eine Schnittstelle.

State.java

public interface State { public void doAction(Context context); }

Schritt 2

Erstelle Entity-Klassen, die die Schnittstelle implementieren.

StartState.java

public class StartState implements State { public void doAction(Context context) { System.out.println("Spieler ist im Startzustand"); context.setState(this); } public String toString(){ return "Startzustand"; } }

StopState.java

public class StopState implements State { public void doAction(Context context) { System.out.println("Spieler ist im Stoppzustand"); context.setState(this); } public String toString(){ return "Stoppzustand"; } }

Schritt 3

ErstelleContextKlasse.

Context.java

public class Context { private State state; public Context(){ state = null; } public void setState(State state){ this.state = state; } public State getState(){ return state; } }

Schritt 4

VerwendungContextUm zu sehen, wann der ZustandStateVerhalten ändert sich, wenn sich der Zustand ändert.

StatePatternDemo.java

public class StatePatternDemo { public static void main(String[] args) { Context context = new Context(); StartState startState = new StartState(); startState.doAction(context); System.out.println(context.getState().toString()); StopState stopState = new StopState(); stopState.doAction(context); System.out.println(context.getState().toString()); } }

Schritt 5

Führen Sie das Programm aus, Ausgabeergebnis:

Player is in start state
Start State
Player is in stop state
Stop State

Weitere Artikel

Weitere Erweiterungen