Menu
Coddy logo textTech

Zustandsmuster

Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy. Lektion 60 von 70.

Das State-Pattern ist ein Verhaltensmuster, das es einem Objekt ermöglicht, sein Verhalten zu ändern, wenn sich sein interner Zustand ändert. Anstatt komplexe bedingte Anweisungen zu verwenden, um verschiedene Zustände zu handhaben, kapseln Sie jeden Zustand in seiner eigenen Klasse und delegieren das Verhalten an das aktuelle Zustandsobjekt.

Das Muster besteht aus drei Komponenten: einer Zustandsschnittstelle, die zustandsspezifisches Verhalten definiert, konkreten Zustandsklassen, die dieses Verhalten implementieren, und einer Kontextklasse, die eine Referenz auf den aktuellen Zustand verwaltet:

public interface IDocumentState
{
    void Publish(Document doc);
}

public class DraftState : IDocumentState
{
    public void Publish(Document doc)
    {
        Console.WriteLine("Moving to moderation");
        doc.SetState(new ModerationState());
    }
}

public class ModerationState : IDocumentState
{
    public void Publish(Document doc)
    {
        Console.WriteLine("Publishing document");
        doc.SetState(new PublishedState());
    }
}

public class PublishedState : IDocumentState
{
    public void Publish(Document doc)
    {
        Console.WriteLine("Already published");
    }
}

Der Kontext hält den aktuellen Zustand und delegiert Aktionen an diesen. Zustandsobjekte können Übergänge auslösen, indem sie SetState() auf dem Kontext aufrufen:

public class Document
{
    private IDocumentState _state = new DraftState();
    
    public void SetState(IDocumentState state) => _state = state;
    
    public void Publish() => _state.Publish(this);
}

var doc = new Document();
doc.Publish();  // Wechsel zur Moderation
doc.Publish();  // Dokument wird veröffentlicht
doc.Publish();  // Bereits veröffentlicht

Das State-Pattern eliminiert ausufernde if-else- oder switch-Anweisungen, die den aktuellen Zustand prüfen. Jede Zustands-Klasse behandelt nur ihr eigenes Verhalten, wodurch der Code einfacher zu warten und um neue Zustände zu erweitern ist.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Ampelsystem mithilfe des Zustandsmusters. Ampeln durchlaufen verschiedene Zustände (rot, gelb, grün), und jeder Zustand bestimmt, was passiert, wenn sich das Licht ändert. Anstatt komplexe Bedingungen zu verwenden, kapselst du jeden Lichtzustand in einer eigenen Klasse.

Du organisierst deinen Code über drei Dateien:

  • TrafficLightState.cs: Definiere ein ITrafficLightState-Interface im Traffic-Namespace mit einer Methode Change(TrafficLight light). Erstelle anschließend drei konkrete Zustandsklassen:
    • RedState – wenn Change aufgerufen wird, gibt die Klasse Red - Stop! Changing to Green... aus und versetzt die Ampel in den Zustand GreenState
    • GreenState – gibt Green - Go! Changing to Yellow... aus und wechselt in den Zustand YellowState
    • YellowState – gibt Yellow - Caution! Changing to Red... aus und wechselt in den Zustand RedState
  • TrafficLight.cs: Erstelle eine TrafficLight-Klasse im selben Namespace. Dies ist deine Kontextklasse, die den aktuellen Zustand verwaltet. Sie soll standardmäßig im Zustand RedState starten und Folgendes enthalten:
    • Eine Methode SetState(ITrafficLightState state), die von Zustandsobjekten verwendet wird, um Übergänge auszulösen
    • Eine Methode Change(), die an die Change-Methode des aktuellen Zustands delegiert
  • Program.cs: Führe alles zusammen, indem du eine TrafficLight erstellst und abhängig von der Eingabe durch die Zustandsänderungen wechselst.

Du erhältst eine Eingabe:

  • Die Anzahl der Änderungen der Ampel (eine Ganzzahl)

Erstelle eine TrafficLight (die bei Rot startet) und rufe Change() so oft wie angegeben auf.

Wenn die Eingabe beispielsweise 3 lautet, sollte die Ausgabe wie folgt aussehen:

Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...
Yellow - Caution! Changing to Red...

Wenn die Eingabe 5 lautet, durchläuft die Ampel wieder alle Zustände:

Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...
Yellow - Caution! Changing to Red...
Red - Stop! Changing to Green...
Green - Go! Changing to Yellow...

Beachte, dass die Klasse TrafficLight keine Logik darüber enthält, was die einzelnen Farben bedeuten oder welcher Zustand als Nächstes kommt – dieses gesamte Wissen befindet sich in den einzelnen Zustandsklassen. Jeder Zustand ist für sein eigenes Verhalten und das Auslösen des Übergangs zum nächsten Zustand verantwortlich!

Probier es selbst

using System;
using Traffic;

class Program
{
    public static void Main(String[] args)
    {
        // Lies die Anzahl der Male, die die Ampel umgeschaltet werden soll
        int n = Convert.ToInt32(Console.ReadLine());

        // TODO: Erstelle eine TrafficLight-Instanz (startet standardmäßig im RedState)

        // TODO: Rufe die Methode Change() n-mal mithilfe einer Schleife auf
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C#-Compiler