Menu
Coddy logo textTech

Wzorzec stanu

Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 98 z 110.

Wzorzec State pozwala obiektowi zmieniać zachowanie, gdy zmienia się jego stan wewnętrzny, sprawiając wrażenie, jakby obiekt zmienił swoją klasę. Zamiast używać złożonych instrukcji warunkowych do obsługi różnych stanów, enkapsulujesz każdy stan we własnej klasie i delegujesz zachowanie do obiektu reprezentującego bieżący stan.

Wzorzec składa się z kontekstu, który przechowuje odwołanie do bieżącego stanu, oraz klas stanu, które definiują zachowanie dla każdego możliwego stanu. Gdy stan kontekstu się zmienia, jego zachowanie zmienia się automatycznie:

abstract class DocumentState {
  void publish(Document doc);
  String getStatus();
}

class DraftState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Moving to review...');
    doc.setState(ReviewState());
  }

  @override
  String getStatus() => 'Draft';
}

class ReviewState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Document published!');
    doc.setState(PublishedState());
  }

  @override
  String getStatus() => 'Under Review';
}

class PublishedState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Already published.');
  }

  @override
  String getStatus() => 'Published';
}

class Document {
  DocumentState _state = DraftState();

  void setState(DocumentState state) => _state = state;
  void publish() => _state.publish(this);
  String getStatus() => _state.getStatus();
}

void main() {
  var doc = Document();
  print(doc.getStatus());  // Wersja robocza
  doc.publish();           // Przekazywanie do recenzji...
  print(doc.getStatus());  // W trakcie recenzji
  doc.publish();           // Dokument opublikowany!
  print(doc.getStatus());  // Opublikowany
}

Każda klasa stanu obsługuje działanie publish() w inny sposób i może przenieść dokument do następnego stanu. Klasa Document nie potrzebuje instrukcji warunkowych, aby sprawdzać swój bieżący stan — po prostu deleguje działanie do aktualnie aktywnego obiektu stanu. Ten wzorzec idealnie sprawdza się w przypadku obiektów o odrębnych trybach działania, takich jak przetwarzanie zamówień, odtwarzacze multimedialne lub systemy przepływu pracy.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system sygnalizacji świetlnej z użyciem wzorca Stan! Utworzysz sygnalizację świetlną, która przechodzi przez różne stany, a każdy stan określa kolor światła i sposób przejścia do następnego stanu.

Podzielisz kod na dwa pliki:

  • traffic_light.dart: Ten plik zawiera klasy stanów i kontekst sygnalizacji świetlnej. Utwórz klasę abstrakcyjną TrafficLightState z dwiema metodami: String getColor(), która zwraca bieżący kolor światła, oraz void next(TrafficLight light), która przełącza światło na następny stan. Zaimplementuj trzy konkretne klasy stanów:
    • RedState — zwraca RED jako kolor i wyświetla Stop! Light is red., gdy wywołana zostanie metoda next(), a następnie przełącza na stan GreenState
    • GreenState — zwraca GREEN jako kolor i wyświetla Go! Light is green., gdy wywołana zostanie metoda next(), a następnie przełącza na stan YellowState
    • YellowState — zwraca YELLOW jako kolor i wyświetla Caution! Light is yellow., gdy wywołana zostanie metoda next(), a następnie przełącza na stan RedState
    Następnie utwórz klasę TrafficLight (kontekst), która rozpoczyna działanie w stanie RedState. Powinna mieć metodę setState() do zmiany bieżącego stanu, metodę getColor(), która deleguje zadanie do bieżącego stanu, oraz metodę change(), która wywołuje next() dla bieżącego stanu.
  • main.dart: Zaimportuj plik sygnalizacji świetlnej i pokaż wzorzec Stan w działaniu. Utwórz obiekt TrafficLight i wyświetl jego początkowy kolor. Następnie wywołaj change() trzy razy, wyświetlając kolor po każdej zmianie. W ten sposób zobaczysz, jak światło przechodzi przez wszystkie stany i wraca do początku.

Zwróć uwagę, że klasa TrafficLight nie potrzebuje żadnych instrukcji warunkowych, aby określić swoje zachowanie — każdy stan zna swój kolor i wie, który stan następuje po nim. Sygnalizacja świetlna po prostu deleguje działanie do aktualnie aktywnego stanu!

Oczekiwany wynik:

RED
Stop! Light is red.
GREEN
Go! Light is green.
YELLOW
Caution! Light is yellow.
RED

Spróbuj swoich sił

import 'traffic_light.dart';

void main() {
  // TODO: Utwórz instancję TrafficLight
  
  // TODO: Wypisz początkowy kolor
  
  // TODO: Wywołaj change() i wypisz kolor (3 razy, aby przejść przez wszystkie stany)
  // Pierwsza zmiana: RED -> GREEN
  
  // Druga zmiana: GREEN -> YELLOW
  
  // Trzecia zmiana: YELLOW -> RED
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Dart online